#include<cstdio> #include<bitset> #include<cstdlib> using namespace std; const int N=1010,M=10010; int n,m,i,j,x,y,e[M][3];char op[5]; int G[N],v[M],nxt[M],ed,from[N],now,g[N][N],d[N],f[N],h,t,q[N],st[N],en[N],dfn,F[N]; inline void add(int x,int y){v[++ed]=y;nxt[ed]=G[x];G[x]=ed;} namespace BIT{ bitset<N>A[N],B[N];//A[i][j]表示j能否走到i,B[i][j]表示i,j是否有共同后继 int d[N],g[N],v[M],nxt[M],ed,h,t,q[N]; inline void add(int x,int y){d[y]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} bool solve(){ for(i=1;i<=n;i++)A[i][i]=1; for(h=i=1;i<=n;i++)if(!d[i])q[++t]=i; while(h<=t)for(i=g[x=q[h++]];i;i=nxt[i]){ A[v[i]]|=A[x]; if(!(--d[v[i]]))q[++t]=v[i]; } if(t<n)return 0; for(i=n;i;i--){ x=q[i]; B[x]=A[x]; for(j=g[x];j;j=nxt[j])B[x]|=B[v[j]]; } return 1; } } int que[N],cnt; void dfs(int x,int y){ if(from[x])return; from[x]=y; for(int i=1;i<=n;i++)if(g[x][i]||g[i][x])dfs(i,y); } void dfs2(int x){ /*que[++cnt]=x; for(int i=1;i<=cnt;i++)if(BIT::B[que[i]][x]==0||BIT::B[x][que[i]]==0){ for(int j=1;j<=cnt;j++)printf("%d\n",que[j]); printf("%d %d\n",que[i],x); exit(0); }*/ st[x]=++dfn; for(int i=G[x];i;i=nxt[i])dfs2(v[i]); en[x]=dfn; cnt--; } inline bool check(int S){ int i; for(ed=0,i=1;i<=n;i++)G[i]=0; for(i=1;i<=n;i++){ if(i==S)F[i]=0; else if(!f[i])F[i]=S; else if(f[i]==S&&f[S])F[i]=f[S]; else F[i]=f[i]; } for(i=1;i<=n;i++)if(F[i])add(F[i],i); dfn=0; dfs2(S); for(i=1;i<=m;i++){ int x=e[i][0],y=e[i][1]; if((st[y]<=st[x]&&en[x]<=en[y])==e[i][2])return 0; } //printf("%d\n",S); //puts("TAK"); for(i=1;i<=n;i++)printf("%d\n",F[i]); return 1; } int main(){ //freopen("reo.in","r",stdin);freopen("reo.out","w",stdout); scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d%s",&x,&y,op); e[i][0]=x,e[i][1]=y; if(op[0]=='T')add(x,y),g[y][x]=1,BIT::add(y,x);else e[i][2]=1; } if(!BIT::solve())return puts("NIE"),0; for(i=1;i<=m;i++)if(e[i][2]){ x=e[i][0],y=e[i][1]; for(j=1;j<=n;j++)if(BIT::A[x][j]&&BIT::B[y][j])g[j][y]=1; } for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(g[i][j])d[j]++; for(h=i=1;i<=n;i++)if(!d[i])q[++t]=i; while(h<=t)for(x=q[h++],i=1;i<=n;i++)if(g[x][i])if(!(--d[i]))q[++t]=i; if(t!=n)return puts("NIE"),0; for(i=1;i<=n;i++)if(!from[i])dfs(i,++now); for(i=2;i<=n;i++){ x=q[i]; for(j=i-1;j;j--)if(BIT::B[x][q[j]]){f[x]=q[j];break;} if(j)continue; for(j=i-1;j;j--)if(from[x]==from[q[j]]){f[x]=q[j];break;} } //x选择y当且仅当x和y必须在一条链上 /*for(i=1;i<=n;i++)if(f[i]){ if(BIT::B[f[i]][i]==0)while(1); if(BIT::B[i][f[i]]==0)while(1); }*/ //printf("->f[422]=%d\n",f[422]); /*for(ed=0,i=1;i<=n;i++)G[i]=0; for(i=1;i<=n;i++)if(f[i])add(f[i],i); dfn=0; for(i=1;i<=n;i++)if(!f[i])dfs2(i);*/ /* for(i=1;i<=m;i++){ int x=e[i][0],y=e[i][1]; if((st[y]<=st[x]&&en[x]<=en[y])==e[i][2])while(1); }*/ //for(i=1;i<=n;i++)printf("%d ",q[i]);puts(""); //for(i=1;i<=n;i++)printf("%d ",f[i]);puts(""); //for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(BIT::B[i][j])printf("%d %d\n",i,j); for(i=1;i<=n;i++)if(check(i))return 0; return puts("NIE"),0; } /* i和j有共同后继 f[i][j] i和j在一条树链上,等价于存在某个点v,使得i,j都能到v*/ /* 对于一个T连通块,入度为0的可以按任意方式串成一条链 剩下的 */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #include<cstdio> #include<bitset> #include<cstdlib> using namespace std; const int N=1010,M=10010; int n,m,i,j,x,y,e[M][3];char op[5]; int G[N],v[M],nxt[M],ed,from[N],now,g[N][N],d[N],f[N],h,t,q[N],st[N],en[N],dfn,F[N]; inline void add(int x,int y){v[++ed]=y;nxt[ed]=G[x];G[x]=ed;} namespace BIT{ bitset<N>A[N],B[N];//A[i][j]表示j能否走到i,B[i][j]表示i,j是否有共同后继 int d[N],g[N],v[M],nxt[M],ed,h,t,q[N]; inline void add(int x,int y){d[y]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} bool solve(){ for(i=1;i<=n;i++)A[i][i]=1; for(h=i=1;i<=n;i++)if(!d[i])q[++t]=i; while(h<=t)for(i=g[x=q[h++]];i;i=nxt[i]){ A[v[i]]|=A[x]; if(!(--d[v[i]]))q[++t]=v[i]; } if(t<n)return 0; for(i=n;i;i--){ x=q[i]; B[x]=A[x]; for(j=g[x];j;j=nxt[j])B[x]|=B[v[j]]; } return 1; } } int que[N],cnt; void dfs(int x,int y){ if(from[x])return; from[x]=y; for(int i=1;i<=n;i++)if(g[x][i]||g[i][x])dfs(i,y); } void dfs2(int x){ /*que[++cnt]=x; for(int i=1;i<=cnt;i++)if(BIT::B[que[i]][x]==0||BIT::B[x][que[i]]==0){ for(int j=1;j<=cnt;j++)printf("%d\n",que[j]); printf("%d %d\n",que[i],x); exit(0); }*/ st[x]=++dfn; for(int i=G[x];i;i=nxt[i])dfs2(v[i]); en[x]=dfn; cnt--; } inline bool check(int S){ int i; for(ed=0,i=1;i<=n;i++)G[i]=0; for(i=1;i<=n;i++){ if(i==S)F[i]=0; else if(!f[i])F[i]=S; else if(f[i]==S&&f[S])F[i]=f[S]; else F[i]=f[i]; } for(i=1;i<=n;i++)if(F[i])add(F[i],i); dfn=0; dfs2(S); for(i=1;i<=m;i++){ int x=e[i][0],y=e[i][1]; if((st[y]<=st[x]&&en[x]<=en[y])==e[i][2])return 0; } //printf("%d\n",S); //puts("TAK"); for(i=1;i<=n;i++)printf("%d\n",F[i]); return 1; } int main(){ //freopen("reo.in","r",stdin);freopen("reo.out","w",stdout); scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d%s",&x,&y,op); e[i][0]=x,e[i][1]=y; if(op[0]=='T')add(x,y),g[y][x]=1,BIT::add(y,x);else e[i][2]=1; } if(!BIT::solve())return puts("NIE"),0; for(i=1;i<=m;i++)if(e[i][2]){ x=e[i][0],y=e[i][1]; for(j=1;j<=n;j++)if(BIT::A[x][j]&&BIT::B[y][j])g[j][y]=1; } for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(g[i][j])d[j]++; for(h=i=1;i<=n;i++)if(!d[i])q[++t]=i; while(h<=t)for(x=q[h++],i=1;i<=n;i++)if(g[x][i])if(!(--d[i]))q[++t]=i; if(t!=n)return puts("NIE"),0; for(i=1;i<=n;i++)if(!from[i])dfs(i,++now); for(i=2;i<=n;i++){ x=q[i]; for(j=i-1;j;j--)if(BIT::B[x][q[j]]){f[x]=q[j];break;} if(j)continue; for(j=i-1;j;j--)if(from[x]==from[q[j]]){f[x]=q[j];break;} } //x选择y当且仅当x和y必须在一条链上 /*for(i=1;i<=n;i++)if(f[i]){ if(BIT::B[f[i]][i]==0)while(1); if(BIT::B[i][f[i]]==0)while(1); }*/ //printf("->f[422]=%d\n",f[422]); /*for(ed=0,i=1;i<=n;i++)G[i]=0; for(i=1;i<=n;i++)if(f[i])add(f[i],i); dfn=0; for(i=1;i<=n;i++)if(!f[i])dfs2(i);*/ /* for(i=1;i<=m;i++){ int x=e[i][0],y=e[i][1]; if((st[y]<=st[x]&&en[x]<=en[y])==e[i][2])while(1); }*/ //for(i=1;i<=n;i++)printf("%d ",q[i]);puts(""); //for(i=1;i<=n;i++)printf("%d ",f[i]);puts(""); //for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(BIT::B[i][j])printf("%d %d\n",i,j); for(i=1;i<=n;i++)if(check(i))return 0; return puts("NIE"),0; } /* i和j有共同后继 f[i][j] i和j在一条树链上,等价于存在某个点v,使得i,j都能到v*/ /* 对于一个T连通块,入度为0的可以按任意方式串成一条链 剩下的 */ |