[洛谷P1330]封锁阳光大学
题目大意:有n个点和m条路(双向),要你在某些点上放“河蟹”来“占领”这个点的所有路,但是任意两只河蟹不能放在有路径连接的两个点上,否则会打架,求最少多少只河蟹使得所有路全被占领,或者不可能全部占领。
算法:BFS(或DFS)染色
思路:因为BFS有分层效果,于是我使用BFS将每个联通块染成黑色和白色。如果两个相同颜色的点有路,说明不能放置河蟹,输出“Impossible”。否则对于每个联通块,算出黑、白各有几个点,取两者较小数加到答案中。所有联通块的点数之和即为答案。
此题数据规模较大,BFS时数组要开小点(内存越小速度似乎越快使用std::queue的请忽略),我丧心病狂地加了读优,加了inline,改了又改,最后数组减小改为循环队列,就过了……
没错就是这个点!!!
C++ Code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #define C c=getchar() using namespace std; int n,m,cnt=0,ans=0,head[200050],next[200050],dist[200050],colour[10005],q[100005],st[100005]; inline int readint(){ int C; while(!isdigit(c))C; int p=0; while(isdigit(c)){ p=p*10+c-'0'; C; } return p; } inline void ins(int x,int y){ cnt++; next[cnt]=head[x]; head[x]=cnt; dist[cnt]=y; cnt++; next[cnt]=head[y]; head[y]=cnt; dist[cnt]=x; } void bfs(int begin){ memset(q,0,sizeof q); memset(st,0,sizeof st); int l=0,r=1; q[1]=begin; st[1]=1; int f[2]={0,1}; colour[begin]=1; while(l!=r){ l=(l+1)%100000; int now=q[l]; for(int i=head[now];i;i=next[i]){ int t=dist[i]; if(colour[t]==-1){ colour[t]=(1+st[l])%2; r=(r+1)%100000; q[r]=t; st[r]=st[l]+1; f[colour[t]]++; }else if(colour[t]==colour[now]){ puts("Impossible"); exit(0); } } } ans+=(f[0]<f[1])?(f[0]):(f[1]); } int main(){ memset(next,0,sizeof next); memset(colour,0xff,sizeof(colour)); memset(dist,0,sizeof dist); n=readint(),m=readint(); for(int i=1;i<=m;i++){ int x,y; x=readint(),y=readint(); ins(x,y); } for(int i=1;i<=n;i++) if(colour[i]==-1)bfs(i); printf("%d\n",ans); return 0; }
----------------------------------------------------------2017.7.10----------------------------------------------------------
补充dfs的代码,思路与bfs一样,dfs是每搜一个换一种颜色。
重点在于,你看dfs的耗时与上面bfs的差距!!!
这差距也太大了吧!!
C++ Code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #define C c=getchar() using namespace std; int n,m,cnt=0,ans=0,head[200050],next[200050],dist[200050],colour[10005]; int f[2]; inline int readint(){ int C; while(!isdigit(c))C; int p=0; while(isdigit(c)){ p=p*10+c-'0'; C; } return p; } inline void ins(int x,int y){ cnt++; next[cnt]=head[x]; head[x]=cnt; dist[cnt]=y; cnt++; next[cnt]=head[y]; head[y]=cnt; dist[cnt]=x; } void dfs(int begin,int co){ colour[begin]=co; f[co]++; for(int i=head[begin];i;i=next[i]){ if(colour[dist[i]]==-1) dfs(dist[i],1-co); else if(colour[dist[i]]==co){ printf("Impossible\n"); exit(0); } } } int main(){ memset(next,0,sizeof next); memset(colour,0xff,sizeof(colour)); memset(dist,0,sizeof dist); n=readint(),m=readint(); for(int i=1;i<=m;i++){ int x,y; x=readint(),y=readint(); ins(x,y); } for(int i=1;i<=n;i++) if(colour[i]==-1){ f[0]=f[1]=0; dfs(i,0); ans+=f[0]<f[1]?f[0]:f[1]; } printf("%d\n",ans); return 0; }