Luogu P1330 封锁阳光大学【Dfs】 By cellur925

题目传送门

这道题我们很容易去想到二分图染色,但是这个题好像又不是一个严格的二分图。

开始的思路: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 }
View Code
扫描二维码关注公众号,回复: 2877074 查看本文章

猜你喜欢

转载自www.cnblogs.com/nopartyfoucaodong/p/9504885.html