SIMPPOLY 2017 ACM-ICPC Asia Amritapuri Regional Contest H DAG圖中判斷是否有一條鏈包含所有的點。
阿新 • • 發佈:2018-12-16
思路: 二分 ans 然後judge judge 的時候先縮點然後生成一個DAG圖,然後跑出一個topo序列,然後判斷相鄰的兩個點之間是否有連邊沒有則不滿足。
程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf =0x3f3f3f3f; typedef pair<int ,int > pii; const int N = 100005; int n,m; vector< pii >ve1[N],ve[N]; int outde[N]; int inde[N]; int ins[N]; int st[N]; int low[N],belong[N],dfn[N]; int top; int Index; int scc; set<int >se[N]; void tarjan(int u) { int v; low[u]=dfn[u]=++Index; st[top++]=u; ins[u]=1; for(int i=0;i<ve[u].size();i++) { v=ve[u][i].first; if(!dfn[v]) { tarjan(v); if(low[v]<low[u]) low[u]=low[v]; } else if(ins[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(low[u]==dfn[u]) { scc++; //printf("*** u %d %d\n",u,scc); do { v=st[--top]; ins[v]=0; belong[v]=scc; }while(v!=u); } } void init() { for(int i=1;i<=n+2;i++) ve[i].clear(); for(int i=0;i<=n+2;i++) { ins[i]=outde[i]=st[i]=belong[i]=low[i]=dfn[i]=inde[i]=0; } top=Index=scc=0; } int jud(int mid) { init(); for(int i=1;i<=n;i++) { for(int j=0;j<ve1[i].size();j++) { if(ve1[i][j].second<=mid) { ve[i].push_back(ve1[i][j]); // printf("******* %d %d %d\n",i,ve1[i][j].first,ve1[i][j].second); // printf("******* %d %d %d\n",i,ve[i][j].first,ve[i][j].second); } } } int uu,vv,u,v; for(int i=1;i<=n;i++) { if(!dfn[i]) tarjan(i); } if(scc==1) return 1; for(int i=0;i<=n+2;i++) se[i].clear(); for(int i=0;i<=n+2;i++) inde[i]=0; for(int i=1;i<=n;i++) { uu=i; for(int j=0;j<ve[i].size();j++) { vv=ve[i][j].first; //printf("**&&&&& uv %d %d\n",uu,vv); u=belong[uu]; v=belong[vv]; if(u==v) continue; if(se[u].count(v)==0) { se[u].insert(v); //printf("hHHHHh %d %d\n",u,v); inde[v]++; } } } /* for(int i=1;i<=scc;i++) { for(set<int >::iterator it=se[i].begin();it!=se[i].end();it++) { printf("** %d %d\n",i,*it); } } */ vector< int >topo; int f=0; queue< int >q; for(int i=1;i<=scc;i++) { if(inde[i]==0) { q.push(i); } } while(!q.empty()) { u=q.front(); q.pop(); topo.push_back(u); for(set<int >::iterator it=se[u].begin();it!=se[u].end();it++) { v=*it; inde[v]--; if(inde[v]==0) { q.push(v); } } } if(topo.size()!=scc) return 0; if(topo.size()<=1) return 1; f=0; for(int i=0;i<topo.size()-1;i++) { u=topo[i]; v=topo[i+1]; if(se[u].count(v)==0) { f=1; break; } } if(f) return 0; return 1; } void init1() { for(int i=0;i<=n+2;i++) { ve[i].clear(); ve1[i].clear(); } memset(st,0,sizeof(st)); memset(ins,0,sizeof(ins)); memset(outde,0,sizeof(outde)); memset(inde,0,sizeof(inde)); memset(low,0,sizeof(low)); memset(belong,0,sizeof(belong)); memset(dfn,0,sizeof(dfn)); top=Index=scc=0; } int main() { int u,v,w; int T; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); init1(); int L,R; R=-1; L=inf; for(int i=1;i<=m;i++) { scanf("%d %d %d",&u,&v,&w); ve1[u].push_back(pii(v,w)); L=min(L,w); R=max(R,w); } int mid; int ans=-1; while(L<=R) { mid=(L+R)>>1; if(jud(mid)) { ans=mid; R=mid-1; } else L=mid+1; } if(ans==-1) { printf("Impossible\n"); } else printf("%d\n",ans); } return 0; } /* 5 4 3 1 2 1 2 3 1 2 4 1 */