標籤:之間 vector hid 沒有 ems mat fine make stl
題意:有一群騎士要坐在一個圓形的桌子上,他們之間有些人相互討厭,所以不能挨著,要求算出一次也不能坐在桌子上的人,每次會議桌子必須奇數個人,一個人不能開會
題解:可以先建一個補圖,要滿足題目條件我們只要找出所有奇圈(奇數個點的環),求出點-雙聯通分量,對於每一個單獨的點-雙連通分量,如果它一定是一個奇圈,那麼不能夠通過二分圖染色,可以通過畫圖驗證這條結論,那麼我們對於所有的奇圈裡的點進行染色,最後輸出沒有染色過的點,因為有可能會出現多次染色的點,所以不能直接每次加點數
坑點:不能用stl,tle了好多發,最後把所有的vector,map都換成了數組就過了,不能用vector存圖,那麼就用我最喜歡的鏈式前向星吧= =
#include<map>#include<set>#include<list>#include<cmath>#include<queue>#include<stack>#include<vector>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define fi first#define se second#define mp make_pair#define pb push_back#define pii pair<int,int>#define C 0.5772156649#define pi acos(-1.0)#define ll long long#define mod 1000000007#define ls l,m,rt<<1#define rs m+1,r,rt<<1|1using namespace std;using namespace __gnu_cxx;const double g=10.0,eps=1e-7;const int N=1000+10,maxn=1000000+10,inf=0x3f3f3f;struct edge{ int to,Next;}e[maxn];int bcc[N];int index,num;int cnt,head[N];int dfn[N],low[N];int bccno[N];struct ewedge{int from,to;};stack<ewedge>s;bool ma[N][N];int in[N],ok[N];int color[N];bool notsub;void add(int x,int y){ e[cnt].to=y; e[cnt].Next=head[x]; head[x]=cnt++; e[cnt].to=x; e[cnt].Next=head[y]; head[y]=cnt++;}void dfs(int u,int f,int p){ if(notsub)return ; color[u]=p; int c=3-p; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to; if(ok[x]) { if(!color[x])dfs(x,u,c); else { if(color[x]!=c)notsub=1; } } }}void tarjan(int u,int f){ low[u]=dfn[u]=++index; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to; ewedge e=(ewedge){u,x}; if(x==f)continue; if(!dfn[x]) { s.push(e); tarjan(x,u); low[u]=min(low[u],low[x]); if(low[x]>=dfn[u]) { int res=0; num++; memset(ok,0,sizeof ok); int be=0; for(;;) { ewedge p=s.top();s.pop(); if(bccno[p.from]!=num) { bcc[res++]=p.from; be=p.from; bccno[p.from]=num; ok[p.from]=1; } if(bccno[p.to]!=num) { bcc[res++]=p.to; be=p.to; bccno[p.to]=num; ok[p.to]=1; } if(p.from==e.from&&p.to==e.to)break; } //判斷是不是二分圖 for(int i=0;i<res;i++) color[bcc[i]]=0; notsub=0; dfs(be,-1,1); if(notsub) { for(int i=0;i<res;i++) in[bcc[i]]=1; } /* cout<<notsub<<"--------"; for(int j=0;j<bcc.size();j++) cout<<bcc[j]<<" "; cout<<endl;*/ } } else { if(dfn[x]<dfn[u])low[u]=min(low[u],dfn[x]); } }}void init(int n){ memset(head,-1,sizeof head); memset(ma,0,sizeof ma); for(int i=1;i<=n;i++) { bccno[i]=dfn[i]=low[i]=in[i]=0; } while(!s.empty())s.pop(); index=num=cnt=0;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { if(!n&&!m)break; init(n); while(m--) { int a,b; scanf("%d%d",&a,&b); ma[a][b]=ma[b][a]=1; } for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(!ma[i][j]) add(i,j); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1); int ans=0; for(int i=1;i<=n;i++) if(in[i]) ans++; printf("%d\n",n-ans); } return 0;}/************************/
View Code
poj2942 點-雙聯通+二分圖染色