题意:亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有 如下要求:1:相互憎恨的两个骑士不能坐在直接相邻的2个位置;2:出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
现在给定准备去开会的骑士数n,再给出m对憎恨关系(表示某2个骑士之间是互相憎恨的),问有多少骑士不管跟哪些骑士都无法组成圆桌会议?
思路:没有矛盾的骑士之间建边,能组成圆桌会议的肯定形成一个环,并且环的点数为奇数。可以用Tarjan求出点双联通分量,判断每个联通分量是否存在 奇环,如果存在奇环的话,该联通分量的所有节点都可以参加会议。一个图是二分图是不存在奇环的充要条件,所以只需要判断该联通分量是否是二分图 即可。
- #include<stdio.h>
- #include<stack>
- #include<math.h>
- #include<string.h>
- const int N=1010;
- using namespace std;
- int cnt[N],low[N],dfs[N],head[N],num,ans,idx,first[N],color[N],flag,n,eenum;
- bool map[N][N],vis[N];
- struct edge
- {
- int st,ed,next;
- }e[N*N],ee[N*N];
- void addedge(int x,int y)
- {
- e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++;
- e[num].st=y;e[num].ed=x;e[num].next=head[y];head[y]=num++;
- }
- void Addedge(int x,int y)
- {
- ee[eenum].st=x;ee[eenum].ed=y;ee[eenum].next=first[x];first[x]=eenum++;
- ee[eenum].st=y;ee[eenum].ed=x;ee[eenum].next=first[y];first[y]=eenum++;
- }
- bool Judge(int u,int cor)//判断二分图
- {
- color[u]=cor;
- int i,v;
- for(i=first[u];i!=-1;i=ee[i].next)
- {
- v=ee[i].ed;
- if(color[v]==-1)
- {
- return Judge(v,cor^1);
- }
- else if(color[v]==color[u])return true;//不是二分图
- }
- return false;
- }
- stack<int>Q;
- void Tarjan(int u,int id)
- {
- int v,i,temp,j;
- dfs[u]=low[u]=idx++;
- for(i=head[u];i!=-1;i=e[i].next)
- {
- v=e[i].ed;
- if(i==(id^1))continue;
- if(dfs[v]==-1)
- {
- Q.push(i);
- Tarjan(v,i);
- low[u]=low[u]>low[v]?low[v]:low[u];
- if(dfs[u]<=low[v])//u为割点
- {
- memset(first,-1,sizeof(first));
- memset(color,-1,sizeof(color));
- eenum=0;
- do
- {
- temp=Q.top();
- Q.pop();
- Addedge(e[temp].st,e[temp].ed);
- }while(temp!=i);//一个双联通分量的所有边
- if(Judge(u,0))//如果不是二分图该联通分量里所有点都可以参加会议
- {
- for(j=0;j<eenum;j+=2)
- vis[ee[j].st]=vis[ee[j].ed]=true;
- }
- }
- }
- else if(low[u]>dfs[v])
- {
- Q.push(i);
- low[u]=dfs[v];
- }
- }
- }
- int main()
- {
- int m,x,y,i,j,sum,Case=0;
- while(scanf("%d%d",&n,&m)!=-1&&n+m)
- {
- memset(head,-1,sizeof(head));
- memset(map,false,sizeof(map));
- num=0;
- for(i=0;i<m;i++)
- {
- scanf("%d%d",&x,&y);
- map[x][y]=map[y][x]=true;
- }
- for(i=1;i<=n;i++)
- {
- for(j=i+1;j<=n;j++)
- if(map[i][j]==false)
- addedge(i,j);
- }
- memset(dfs,-1,sizeof(dfs));
- memset(vis,false,sizeof(vis));
- ans=idx=0;sum=0;
- for(i=1;i<=n;i++)//图可能不连通
- {
- if(dfs[i]==-1)
- Tarjan(i,-1);
- }
- for(i=1;i<=n;i++)
- if(!vis[i])
- sum++;
- printf("%d\n",sum);
- }
- return 0;
- }