codeforces 1027F Session in BSU
阿新 • • 發佈:2018-12-16
首先我們把日期看成點,每個考試都連線了兩個點,而合法的情況就是每條邊都至少有一個點和他配對,和二分圖匹配很像。。
但是時間明顯不夠,那麼我們可以轉換思路,通過連邊,原圖變為了一些連通塊,而對於每個連通塊,就有以下幾種情況
1.這個連通塊是個樹,那麼每條邊都有點,還多出一個點,所以最後要找的就是次大的點。
2.這個連通塊是一個基環樹(就是隻有一個環的樹),那麼每個點正好對應一條邊,要用的就是最大的點。
3.這個連通塊的邊數>點數,那麼一定不合法,輸出-1即可。
PS:對於2和3情況的判定我換了好幾種方法終於對了。。。
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<map> #include<vector> using namespace std; map<int,int>M,N; int cnt,n,used[2000006],hh[2000006]; vector<int>W[2000006]; int maxx,flag,cimax,ans; struct dd { int u,v; }ddd[1000006]; void dfs(int u,int fa) { used[u]++; if(u<maxx)cimax=max(cimax,u); else if(u>maxx) cimax=maxx,maxx=u; int l=W[u].size()-1; for(int i=0;i<=l;i++) { if(W[u][i]==fa)continue; if(used[W[u][i]]) { used[W[u][i]]++; if(used[W[u][i]]==2) { flag++; if(flag>2)//有多組環不合法 { printf("-1"); exit(0); } } if(used[W[u][i]]>2)//一個點被超過2條邊連不合法 { printf("-1"); exit(0); } continue; } dfs(W[u][i],u); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&ddd[i].u,&ddd[i].v); hh[++cnt]=ddd[i].u,hh[++cnt]=ddd[i].v; } sort(hh+1,hh+1+cnt);int tr=0; for(int i=1;i<=cnt;i++) { if(!M[hh[i]])M[hh[i]]=++tr,N[tr]=hh[i]; } for(int i=1;i<=n;i++) { W[M[ddd[i].u]].push_back(M[ddd[i].v]); W[M[ddd[i].v]].push_back(M[ddd[i].u]); } for(int i=1;i<=tr;i++) { maxx=0,cimax=0,flag=0; if(!used[i]) { dfs(i,i); if(flag) { ans=max(ans,maxx); }else { ans=max(ans,cimax); } } } printf("%d",N[ans]); return 0; }