标签:
好久没敲了,手生。
题意:给一个图,要求是没有环,并且能从一点出发一笔画完所有点。定性判断出来。
想恢复一下算法,判断矛盾用的强连通性的tarjan,不能确定用的模拟。
#include<iostream> #include<cstdio> #include<set> #include<stack> #include<vector> using namespace std; int fa[30105]; int n,m; int ind[30028]; int find(int x) { if(x==fa[x])return x; fa[x]=find(fa[x]); return fa[x]; } int e[100154][3];int head[30023];int nume; void inline adde(int i,int j) { e[nume][0]=j;e[nume][1]=head[i];head[i]=nume++; } struct zz { int x,y; char t; }; int ins[20009];stack<int>sta;int low[20025];int dfn[20025]; int times;int vis[20025];int scc[20251];int numb=0; void tarjan(int u) { dfn[u]=low[u]=times++; ins[u]=1; sta.push(u); for(int j=head[u];j!=-1;j=e[j][1]) { int v=e[j][0]; if(!vis[v]) { vis[v]=1; tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(ins[v]) { if(dfn[v]<low[u])low[u]=dfn[v]; } } if(low[u]==dfn[u]) { numb++; int cur; do { cur=sta.top(); sta.pop(); ins[cur]=0; scc[cur]=numb; }while(cur!=u); } } int judge() { int ss=-1; int cnt=0;int numv=0; set<int>temp; for(int i=0;i<n;i++) { int tx=find(i); temp.insert(tx); if(ind[tx]==0&&tx==i) //开始没有加这个后面条件,WA了好几发。。。 { ss=tx; cnt++; } } numv=temp.size(); for(int i=0;i<n;i++) { int tx=find(i); if(!vis[tx]) { vis[tx]=1; tarjan(tx); } } if(numb!=numv)return 1; //有矛盾 if(cnt!=1)return 2; int cur=ss; while(numv!=0) { cnt=0; for(int j=head[cur];j!=-1;j=e[j][1]) { int to=e[j][0]; ind[to]--; if(ind[to]==0) { cur=to; cnt++; } } if(cnt>1)return 2; numv--; } return 0; } void init() { for(int i=0;i<10005;i++) { fa[i]=i; head[i]=-1; low[i]=dfn[i]=0; scc[i]=vis[i]=ins[i]=ind[i]=0; } numb=times=nume=0; } int main() { while(~scanf("%d%d",&n,&m)) { int marks=0; int aa,bb;char temp; init(); vector<zz>my; for(int i=0;i<m;i++) { cin>>aa>>temp>>bb; if(temp=='=') { int xx=find(aa); int yy=find(bb); if(xx!=yy)fa[xx]=yy; } else { zz cur; cur.x=aa;cur.y=bb;cur.t=temp; my.push_back(cur); } } for(int i=0;i<my.size();i++) { if(my[i].t=='<') { int xx=find(my[i].x); int yy=find(my[i].y); if(xx==yy)marks=1; adde(yy,xx); ind[xx]++; } else { int xx=find(my[i].x); int yy=find(my[i].y); if(xx==yy)marks=1; adde(xx,yy); ind[yy]++; } } int ans=judge(); if(n==0) ans=0; if(ans==2&&marks!=1) printf("UNCERTAIN\n"); else if(ans==1||marks==1) printf("CONFLICT\n"); else printf("OK\n"); } return 0; }
传统方法: ufset拓扑:
#include<iostream> #include<cstdio> #include<set> #include<stack> #include<vector> using namespace std; const int maxn=100004; int fa[maxn]; int n,m; int ind[maxn]; int sums=0; vector<vector<int> >e(maxn); int find(int x) { if(x==fa[x])return x; fa[x]=find(fa[x]); return fa[x]; } struct zz { int x,y; char t; }; int judge() { int ans=0; stack<int>mys; for(int i=0;i<n;i++) { int tx=find(i); if(ind[tx]==0&&tx==i) { mys.push(tx); } } while(!mys.empty()) { int cnt=0; int cur=mys.top(); if(mys.size()!=1)ans=2; mys.pop(); sums--; for(int i=0;i<e[cur].size();i++) { int to=e[cur][i]; ind[to]--; if(ind[to]==0) { mys.push(to); } } } if(sums!=0)ans=1; return ans; } void init() { for(int i=0;i<maxn-1;i++) { fa[i]=i; ind[i]=0; e[i].clear(); } sums=n; } int main() { while(~scanf("%d%d",&n,&m)) { int aa,bb;char temp; init(); vector<zz>my; for(int i=0;i<m;i++) { cin>>aa>>temp>>bb; if(temp=='=') { int xx=find(aa); int yy=find(bb); if(xx!=yy){fa[xx]=yy;sums--;} } else { zz cur; cur.x=aa;cur.y=bb;cur.t=temp; my.push_back(cur); } } for(int i=0;i<my.size();i++) { if(my[i].t=='<') { int xx=find(my[i].x); int yy=find(my[i].y); e[yy].push_back(xx); ind[xx]++; } else if(my[i].t=='>') { int xx=find(my[i].x); int yy=find(my[i].y); e[xx].push_back(yy); ind[yy]++; } } int ans=judge(); if(n==0) ans=0; if(ans==2) printf("UNCERTAIN\n"); else if(ans==1) printf("CONFLICT\n"); else printf("OK\n"); } return 0; }
标签:
原文地址:http://blog.csdn.net/u011498819/article/details/44422649