「题解」:图论专题总结
T1菜肴制作:拓扑排序+大根堆
卡了好一会儿才过掉。正序拓扑的话贪心策略会出错。
保证先输出小的,倒序拓扑保证先搞大的。然后插到大根堆里。
每次取出最大的(堆顶)进行拓扑扩展。pop出来的直接扔进栈里。
多判有点恶心。记得清空(我就因为tot没清空,样例第三组单测正确,多测就错。。)
还有一个特殊判断:栈内元素个数与本身元素个数是否相符。
不相符就是剩下了环搞不出来,impossible就行了。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<stack> #define rint register int using namespace std; int T,n,m,a,b,tot,first[100003]; int du[100003]; struct node{ int u,v,nxt; }; bool pan=0,vis[100003]; inline void add(int uu,int vv,node edge[]) { ++tot; edge[tot].u=uu; edge[tot].v=vv; edge[tot].nxt=first[uu]; first[uu]=tot; } int main() { scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); memset(vis,0,sizeof(vis)); memset(du,0,sizeof(du)); memset(first,0,sizeof(first)); tot=0; priority_queue <int> q; stack <int> s; node edge[100003]; for(rint i=1;i<=m;++i) { scanf("%d %d",&a,&b); add(b,a,edge);du[a]++; } for(rint i=1;i<=n;++i) { if(!du[i])q.push(i); vis[i]=1; } if(q.empty()){cout<<"Impossible!"<<endl;continue;} while(!q.empty()) { int xx=q.top();s.push(xx);q.pop(); // cout<<xx<<endl; pan=0; for(rint i=first[xx];i;i=edge[i].nxt) { int yy=edge[i].v; du[yy]--; if(!du[yy]) { pan=1; q.push(yy); // cout<<"yy"<<yy<<endl; vis[yy]=1; } } // if(pan==0&&q.empty()){cout<<"Impossible!"<<endl;break;} } // if(pan==0)continue; if(s.size()!=n){cout<<"Impossible!"<<endl;continue;} while(!s.empty()) { cout<<s.top()<<' '; s.pop(); } cout<<endl; } }
T2矩阵游戏:二分图
锝瑟一把这题全hzoj我是第一个A掉的
二分图,一开始还真没想起来。查bzoj上这道题的时候撇了一眼看到了二分图三个字。
好的。(不要脸)但是真的忘了啊QAQ只好翻出ftp里尘封多年的二分图ppt。
手码了一遍匈牙利感觉还不错。
挺基础,行列分别建点,黑格建边,跑一边匈牙利,用黑格去匹配行和列。
然而没认真看题,人家让输出“Yes”或“No”,我输出“YES”“NO”完美w0。。。
加了一堆卡常特盘,148毫算是挺快的了吧?(wtf 102ms!收小的一拜)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #include<algorithm> using namespace std; const int N=205; int a[N][N]; int vis[N],matx[N],maty[N]; int tot; int n; int hun(int x) { for(int i=1;i<=n;i++) { //int y=to[i]; if(!vis[i]&&a[x][i]) { vis[i]=1; if(maty[i]==-1||hun(maty[i])) { maty[i]=x; matx[x]=i; return 1; } } } return 0; } int main(){ int T; scanf("%d",&T); while(T--){ tot=0; memset(maty,-1,sizeof(maty)); memset(matx,-1,sizeof(matx)); scanf("%d",&n); int cnt=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); int ans=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(hun(i)) ans++; } //cout<<ans<<endl; if(ans!=n){ printf("No "); } else puts("Yes "); } }