该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列。是典型的拓扑排序,但输出格式上确有三种形式:
1.该字母序列有序,并依次输出;
2.该序列不能判断是否有序;
3.该序列字母次序之间有矛盾,即有环存在。
而这三种形式的判断是有顺序的:先判断是否有环(3),再判断是否有序(1),最后才能判断是否能得出结果(2)。注意:对于(2)必须遍历完整个图,而(1)和(3)一旦得出结果,对后面的输入就不用做处理了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 7 using namespace std; 8 9 const int N=5005; 10 vector<int>g[N]; 11 int dfn[N],low[N],dg[N],tim; 12 bool vis[N],map[N][N]; 13 int n,r; 14 15 void tarjan(int u,int fa) 16 { 17 dfn[u]=low[u]=++tim; 18 vis[u]=1; 19 for (int i=0;i<g[u].size();i++) 20 { 21 int v=g[u][i]; 22 if (v==fa) continue; 23 if (!dfn[v]) 24 { 25 tarjan(v, u); 26 low[u]=min(low[u],low[v]); 27 } 28 else if (vis[v]) low[u]=min(low[u],dfn[v]); 29 } 30 } 31 void init() 32 { 33 memset(dfn,0,sizeof(dfn)); 34 memset(low,0,sizeof(low)); 35 memset(vis,0,sizeof(vis)); 36 tim=0; 37 tarjan(1,-1); 38 } 39 int main() 40 { 41 while (~scanf("%d%d",&n,&r)) 42 { 43 for (int i=1;i<=n;i++) 44 g[i].clear(); 45 memset(map,0,sizeof(map)); 46 int u,v; 47 for (int i=0;i<r;i++) 48 { 49 scanf("%d%d",&u,&v); 50 if (!map[u][v]) 51 { 52 g[u].push_back(v); 53 g[v].push_back(u); 54 map[u][v]=map[v][u]=1; 55 } 56 } 57 58 init(); 59 memset(dg,0,sizeof(dg)); 60 61 for (int u=1;u<=n;u++) 62 for (int i=0;i<g[u].size();i++) 63 { 64 int v=g[u][i]; 65 if (low[u]!=low[v]) dg[low[u]]++; 66 } 67 68 int cnt=0; 69 for (int i=1;i<=n;i++) 70 if (dg[i]==1) cnt++; 71 printf("%d ",(cnt+1)/2); 72 } 73 }