给你一幅图,问你最少占领几个点,能够封锁阳光大学,但是不能占领一条边的两个点
就是每条边有且只有一个点能被占领,这么一来,每个连通分量只可能有两个方案(占领变不占领),所以直接搜,加上少的就好了
1 #include<iostream> 2 using namespace std; 3 const int N=1e5+100; 4 int cnt=0; 5 struct node 6 { 7 int to;//到的点 8 int from;//出发点相同的边在数组中的位置 9 }edge[N]; 10 int head[N]; 11 void add(int a,int b) 12 { 13 cnt++; 14 edge[cnt].to=b;//这条边到达的点 15 edge[cnt].from=head[a];//存下目前最新的和我同出发点的边所在位置(因为我就要替换他了) 16 head[a]=cnt; 17 }//链式向前星(难) 18 19 bool used[N]; 20 int color[N]; 21 int sum[2]; 22 bool dfs(int now,int col) 23 { 24 if(used[now]) 25 { 26 if(color[now]==col)//如果走完一遍回来,发现自个儿的颜色还得变,那就是impossible了 27 { 28 return true; 29 } 30 return false; 31 } 32 used[now]=true;//标记 33 color[now]=col;//记录现在在的点的颜色 34 sum[col]++;//这种颜色的点加一 35 bool flag=1; 36 for(int i=head[now];i!=0&&flag;i=edge[i].from)//遍历所有的边,可以理解为深度遍历 37 { 38 if(!dfs(edge[i].to,!col))//如果下一个点出问题了,一路返回false 39 flag=0; 40 } 41 return flag; 42 } 43 int main(void) 44 { 45 int n,m; 46 cin>>n>>m; 47 for(int i=1;i<=m;i++) 48 { 49 int a,b; 50 cin>>a>>b; 51 add(a,b);//无向图 52 add(b,a); 53 } 54 int ans=0; 55 for(int i=1;i<=n;i++) 56 { 57 if(used[i]) 58 continue; 59 sum[0]=sum[1]=0;//初始化 60 if(!dfs(i,0))//如果不能完成染色,直接输出im 61 { 62 cout<<"Impossible"; 63 return 0; 64 } 65 ans+=min(sum[0],sum[1]);//加上小的 66 } 67 cout<<ans; 68 return 0; 69 }
原文地址:https://www.cnblogs.com/greenofyu/p/12229916.html
时间: 2024-10-26 00:16:16