【洛谷P1330】封鎖陽光大學
阿新 • • 發佈:2018-11-29
題目大意:給定一個 N 個點,M 條邊的無向圖,現在要選出圖中的一個頂點集合,使得集合種的頂點不直接相鄰,且這張圖的所有邊都被該頂點集合覆蓋,求該頂點集合大小的最小值,若不能完成覆蓋,則輸出 impossible。
題解:由於要求集合中頂點不能相鄰,且每條邊都要被覆蓋,則對於任意一條邊來說,連線該邊的兩個頂點必有且只有一個在該集合中。對於這種相鄰頂點不能在同一個集合中的性質,可以考慮對圖進行染色的操作,即:相鄰頂點的顏色不同,看是否可以用兩個顏色染完整張圖而不發生衝突,染色時順便記錄下每種顏色的頂點個數,個數少的即為答案貢獻的一部分。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxv=1e4+10; const int maxe=1e5+10; inline int read(){ int x=0,f=1;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch)); do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch)); return f*x; } struct node{ int nxt,to; }e[maxe<<1]; int tot=1,head[maxv]; int n,m,ans,sum[2]; bool vis[maxv],cor[maxv]; inline void add_edge(int from,int to){ e[++tot]=node{head[from],to},head[from]=tot; } void read_and_parse(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int from=read(),to=read(); add_edge(from,to),add_edge(to,from); } } bool dfs(int u,int c){ if(vis[u])return cor[u]==c; vis[u]=1,++sum[cor[u]=c]; for(int i=head[u];i;i=e[i].nxt)if(!dfs(e[i].to,c^1))return 0; return 1; } void solve(){ for(int i=1;i<=n;i++)if(!cor[i]){ sum[0]=sum[1]=0; if(!dfs(i,0)){puts("Impossible");return;} ans+=min(sum[0],sum[1]); } printf("%d\n",ans); } int main(){ read_and_parse(); solve(); return 0; }