这道题我们很容易去想到二分图染色,但是这个题好像又不是一个严格的二分图。
开始的思路:dfs每个点,扫与他相邻的每个点,如果没访问,染相反颜色;如果访问过,进行检查,如果不可行,直接结束程序。每dfs一次,计数器加1.--40pts
然鹅这个思路存在(很明显的)漏洞:我们统计的是默认初始颜色所染的个数,但是题目中求的是最小的河蟹放置个数,很有可能相反颜色放的更少。--100pts
另外在题解中经某位高人指点,终于懂得
1 for(int i=1;i<=n;i++) 2 if(!vis[i]) dfs(i)
这种语句的真正含义!其实在1~n的循环中,实际从主程序中调用了几次Dfs函数,就有几个联通块。(很多情况下图不保证联通)因为我们回想大法师的真正含义,他是不撞南墙不回头(回溯)的。除非没有新的南墙可撞。
然后我们就愉快的AC了。
Code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 int n,m,a,b,ans,tot; 7 int head[10090],vis[10090],sum[5],color[10090]; 8 struct node{ 9 int to,next; 10 }edge[200090]; 11 12 void add(int x,int y) 13 { 14 edge[++tot].to=y; 15 edge[tot].next=head[x]; 16 head[x]=tot; 17 } 18 19 void dfs(int u,int pts) 20 { 21 vis[u]=1;color[u]=pts;sum[pts]++; 22 for(int i=head[u];i;i=edge[i].next) 23 { 24 int y=edge[i].to; 25 if(vis[y]) 26 { 27 if(color[y]!=3-pts) 28 { 29 printf("Impossible"); 30 exit(0); 31 } 32 } 33 else dfs(y,3-pts); 34 } 35 } 36 37 int main() 38 { 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=m;i++) 41 scanf("%d%d",&a,&b),add(a,b),add(b,a); 42 for(int i=1;i<=n;i++) 43 { 44 sum[1]=0,sum[2]=0; 45 //实质在扫联通块 46 if(!vis[i]) dfs(i,1),ans+=min(sum[1],sum[2]); 47 } 48 printf("%d",ans); 49 return 0; 50 }
原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9504885.html
时间: 2024-10-13 21:06:16