[POI2014]Rally
OJ题号:
BZOJ3832、洛谷3573
思路:
建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$。
对于每条边$i$,设定一个权值$w_i=diss_{i.from}+dist_{i.to}-1$。
表示原图中包含这条边的从$S$到$T$的最长路。
然后按照拓扑序删点$x$,用堆维护不包含$x$的最长路长度。
然而一次性不能把所有边放进去,不然会MLE一个点(因为这个调了一个晚上)。
应该在换$x$的时候,把老$x$的出边重新加入,并将新$x$的入边删去。
注意开的数组不能太多,能合并的信息尽量合并,(比如所有边正反边用一个数组存,取值的时候用异或),不然把堆修改以后还是会MLE。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #include<ext/pb_ds/priority_queue.hpp> 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 const int inf=0x7fffffff; 14 const int V=500002,E=2000000; 15 struct Edge { 16 int from,to; 17 }; 18 Edge e[E]; 19 int w[E]; 20 int s,t; 21 int n,m; 22 std::vector<int> eids[V],eidt[V]; 23 int inds[V]={0},indt[V]={0}; 24 inline void add_edge(const int u,const int v,int *ind,std::vector<int> *eid,const int i) { 25 eid[u].push_back(i); 26 ind[v]++; 27 } 28 int diss[V]={0},dist[V]={0}; 29 std::queue<int> top; 30 inline void Kahn(const int s,std::vector<int> *eid,int *dis,int *ind,const int op=0) { 31 std::queue<int> q; 32 q.push(s); 33 while(!q.empty()) { 34 int x=q.front(); 35 q.pop(); 36 if(op) top.push(x); 37 for(register unsigned i=0;i<eid[x].size();i++) { 38 int y=e[eid[x][i]].from^e[eid[x][i]].to^x; 39 dis[y]=std::max(dis[y],dis[x]+1); 40 if(!--ind[y]) q.push(y); 41 } 42 } 43 } 44 __gnu_pbds::priority_queue<int> q; 45 __gnu_pbds::priority_queue<int>::point_iterator p[E]; 46 int v,ans=inf; 47 int cnt=0; 48 inline void solve() { 49 while(!top.empty()) { 50 int x=top.front(); 51 top.pop(); 52 for(register unsigned i=0;i<eidt[x].size();i++) { 53 q.erase(p[eidt[x][i]]); 54 } 55 if(!q.empty()) { 56 if((x!=s)&&(x!=t)&&(q.top()<ans)) { 57 ans=q.top(); 58 v=x; 59 } 60 } 61 for(register unsigned i=0;i<eids[x].size();i++) { 62 p[eids[x][i]]=q.push(w[eids[x][i]]); 63 } 64 } 65 } 66 int main() { 67 n=getint(),m=getint(); 68 s=0,t=n+1; 69 for(register int i=1;i<=n;i++) { 70 e[cnt].from=s,e[cnt].to=i; 71 add_edge(s,i,inds,eids,cnt); 72 add_edge(i,s,indt,eidt,cnt); 73 cnt++; 74 } 75 for(register int i=0;i<m;i++) { 76 int &u=e[cnt].from=getint(),&v=e[cnt].to=getint(); 77 add_edge(u,v,inds,eids,cnt); 78 add_edge(v,u,indt,eidt,cnt); 79 cnt++; 80 } 81 for(register int i=1;i<=n;i++) { 82 e[cnt].from=i,e[cnt].to=t; 83 add_edge(i,t,inds,eids,cnt); 84 add_edge(t,i,indt,eidt,cnt); 85 cnt++; 86 } 87 Kahn(s,eids,diss,inds,1); 88 Kahn(t,eidt,dist,indt); 89 for(register int i=0;i<cnt;i++) { 90 w[i]=diss[e[i].from]+dist[e[i].to]-1; 91 } 92 solve(); 93 printf("%d %d\n",v,ans); 94 return 0; 95 }