P4381萌新继续求助,经过一下午的奋斗,45->85了(
  • 板块学术版
  • 楼主PCCP
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/2/3 21:05
  • 上次更新2023/10/24 01:50:05
查看原帖
P4381萌新继续求助,经过一下午的奋斗,45->85了(
310773
PCCP楼主2023/2/3 21:05

发现自己的做法假了之后,改成了单调队列正解了。但是还是WA了#3#4,TLE #15。来回改了2个小时,但是因为拿不到测试点,还没有成功,求各位大佬帮帮忙看看代码,救救孩子吧。

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
const int N=2e6+10;
int n,a[N];
#define ll long long
#define int long long
int he[N],ne[N],to[N],tot=1;
long long w[N],d[N],dist[N],ans,sum,ringlen;
ll read(){
	ll x=0;char ch=getchar();
	while(ch<'0'||'9'<ch) ch=getchar();
	while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar(); }
	return x;
}
void addedge (int x,int y,long long z){
	to[++tot]=y;
	ne[tot]=he[x];
	he[x]=tot;
	w[tot]=z;
}
int low[N],dfo[N],cnt=0,edcccnt=0;
stack <int> q;
vector <int> edcc[N];
bool st[N],bridge[N],node[N],vis[N];
void tarjan(int now,int inedge){
	dfo[now]=low[now]=++cnt;
	q.push(now);
	st[now]=1;
	for(int i=he[now];i;i=ne[i]){
		int v=to[i];
		if(!dfo[v]){
			tarjan(v,i);
			low[now]=min(low[now],low[v]);
			if(low[v]>dfo[now]){
				bridge[i]=bridge[i^1]=true;
				++edcccnt;
				int p;
				do{
					p=q.top();
					edcc[edcccnt].push_back(p);
					st[p]=0;
					q.pop();
				}
				while(p!=v);
				if(edcc[edcccnt].size()==1){
					edcc[edcccnt].clear();
					--edcccnt;
				}
			}
		}
		else if(i!=(inedge^1)){
			low[now]=min(low[now],dfo[v]);
		}
	}
}
void dp(int now){
	st[now]=true;
	for(int i=he[now];i;i=ne[i]){
		int v=to[i];
		if(st[v]||node[v]){
			continue;
		}
		dp(v);
		sum=max(sum,(long long)d[now]+d[v]+w[i]);
		d[now]=max(d[now],(long long)d[v]+w[i]);
	}
}
int dfs(int now,int fa,long long s,int inedge){
//	cout<<"from "<<fa<<" to "<<now<<" the s: "<<s<<endl;
	dist[++cnt]=s;
	a[cnt]=now;
	if(vis[now]==true){
		return s;
	}
	vis[now]=true;
	for(int i=he[now];i;i=ne[i]){
		int v=to[i];
		if(node[v]==false||i==(inedge^1)){
			continue;
		}
//		cout<<"next is "<<v<<endl; 
		return dfs(v,now,s+w[i],i);
	}
}
signed main(){
	n=read();
	int x,y;
	long long z;
	for(int i=1;i<=n;i++){
		y=read();z=read();
		x=i;
		if(x==y){
			continue;
		}
		addedge(x,y,z);
		addedge(y,x,z);
	}
	for(int i=1;i<=n;i++){
		if(!st[i]){
			addedge(i+n,i,0);
			tarjan(i+n,0);
		}
	}
	memset(st,0,sizeof st);
	for(int i=1;i<=edcccnt;i++){
		sum=cnt=0;
		vector<int>::iterator it;
		for(it=edcc[i].begin();it!=edcc[i].end();it++){
			node[*it]=true;
 			// cout<<*it<<" ";
		}
//  		cout<<endl;
		ringlen=dfs(*edcc[i].begin(),0,0,-1);
		for(int j=1;j<=cnt;j++){
// 			cout<<j<<" : "<<a[j]<<" "<<dist[j]<<endl;
		}
		for(int j=cnt+1;j<=(cnt-1)*2;j++){
			a[j]=a[j-(cnt-1)];
			dist[j]=dist[j-1]+(dist[j-(cnt-1)]-dist[j-(cnt-1)-1]);
// 			cout<<j<<" : "<<a[j]<<" "<<dist[j]<<endl;
		}
		--cnt;
// 		cout<<"ringlen: "<<ringlen<<endl;
// 		cout<<"cnt : "<<cnt<<endl;
		for(int j=1;j<=cnt;j++){
			dp(a[j]);
//			cout<<a[j]<<" : "<<sum<<endl;
		}
		int l=1,r=0,q[N];
		for(int k=1;k<=2*cnt;k++){
			while(l<=r&&k-q[l]>=cnt){
				l++;
			}
			if(l<=r){
				sum=max(sum,d[a[k]]+d[a[q[l]]]+(dist[k]-dist[q[l]]));
			}
			while(l<=r&&d[a[k]]-dist[k]>=d[a[q[r]]]-dist[q[r]]){
				r--;
			}
			q[++r]=k;
//			cout<<l<<" - "<<r<<" "<<dist[r]-dist[l]<<" "<<endl;
		}
		ans+=sum;
	}
	printf("%lld\n",ans);
} 
2023/2/3 21:05
加载中...