好久没敲了,手生。
题意:给一个图,要求是没有环,并且能从一点出发一笔画完所有点。定性判断出来。
想恢复一下算法,判断矛盾用的强连通性的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;
}