题面还好,就不描述了
重点说题解:
由于仇恨关系不好处理,所以可以搞补图存不仇恨关系,
如果一个桌子上面的人能坐到一起,显然他们满足能构成一个环
所以跑点双联通分量
求点双联通分量我用的是向栈中push边的方法
请注意:只向栈中push树枝边
这样每次一对父子(u,v)
如果low[v]<=dfn[u] 显然u是v所在点双联通分量的割点
所以栈中边(u,v)之前的边都pop,他们连接的点构成点双联通分量
我们找到一个点双联通分量之后,由于要求奇数个人坐一桌
所以满足存在奇环,dfs染色即可
注意割点可能属于很多点双联通分量,所以染完色之后需要给他把颜色去掉
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<stack> 6 #define N 1010 7 using namespace std; 8 int n,m,head[N],adj[N][N],ans,dfn[N],low[N],ok[N],ecnt,indx,clr[N],inst[N]; 9 int read() 10 { 11 int ret=0,neg=1; 12 char j=getchar(); 13 for (;j<'0' || j>'9';j=getchar()) 14 if (j=='-') neg=-1; 15 for (;j<='9' && j>='0';j=getchar()) 16 ret=ret*10+j-'0'; 17 return ret*neg; 18 } 19 struct edge 20 { 21 int u,v,nxt; 22 }e[N*N]; 23 stack <edge> stk; 24 stack <int> tmp; 25 void add(int u,int v) 26 { 27 e[++ecnt].u=u; 28 e[ecnt].v=v; 29 e[ecnt].nxt=head[u]; 30 head[u]=ecnt; 31 } 32 void getG()//还是推荐链式前向星存图= = 33 { 34 for (int i=1,u,v;i<=m;i++) 35 { 36 u=read(),v=read(); 37 adj[u][v]=1; 38 adj[v][u]=1; 39 } 40 for (int i=1;i<=n;i++) 41 for (int j=1;j<=n;j++) 42 if (adj[i][j]==0 && i!=j) add(i,j); 43 } 44 int dfs(int u,int nw)//染色 45 { 46 int ret=1; 47 for (int i=head[u];i;i=e[i].nxt) 48 { 49 int v=e[i].v; 50 if (inst[v]==1) 51 { 52 if (clr[v]==-1) 53 { 54 clr[v]=1-nw; 55 ret&=dfs(v,1-nw); 56 } 57 else 58 if (clr[v]==nw) ret=0; 59 } 60 } 61 return ret; 62 } 63 void init() 64 { 65 memset(ok,0,sizeof(ok)); 66 memset(head,0,sizeof(head)); 67 memset(adj,0,sizeof(adj)); 68 memset(inst,0,sizeof(inst)); 69 ecnt=1; 70 memset(dfn,0,sizeof(dfn)); 71 memset(clr,-1,sizeof(clr)); 72 indx=0; 73 ans=0; 74 } 75 void tar(int u,int fa) 76 { 77 dfn[u]=low[u]=++indx; 78 for (int i=head[u];i;i=e[i].nxt) 79 { 80 int v=e[i].v; 81 if (!dfn[v]) 82 { 83 stk.push(e[i]); 84 tar(v,u); 85 low[u]=min(low[u],low[v]); 86 if (low[v]>=dfn[u])//题解找双联通分量部分 87 { 88 while (1) 89 { 90 edge e=stk.top(); 91 stk.pop(); 92 inst[e.u]=1; 93 inst[e.v]=1; 94 tmp.push(e.u); 95 tmp.push(e.v); 96 if (e.u==u && e.v==v) break; 97 } 98 clr[u]=1; 99 if (dfs(u,1)==0) 100 while (!tmp.empty()) 101 { 102 ok[tmp.top()]=1; 103 inst[tmp.top()]=0; 104 tmp.pop(); 105 } 106 else while (!tmp.empty()) inst[tmp.top()]=0,tmp.pop(); 107 clr[u]=-1; 108 } 109 } 110 else if (v!=fa) 111 low[u]=min(low[u],dfn[v]); 112 } 113 } 114 int main() 115 { 116 n=read(); 117 m=read(); 118 while (n || m) 119 { 120 init(); 121 getG(); 122 for (int i=1;i<=n;i++) 123 if (!dfn[i]) tar(i,-1); 124 for (int i=1;i<=n;i++) 125 ans+=ok[i]; 126 printf("%d ",n-ans); 127 n=read(),m=read(); 128 } 129 return 0; 130 }