染色 能否構成二分圖 存在多個連通快
阿新 • • 發佈:2018-12-12
#include<iostream> #include<cstring> #include<cmath> #include<string> #include<map> #include<vector> #include<set> #include<queue> #include<cstdio> #include<cstdlib> #include<algorithm> #include<functional> using namespace std; #define inf 0x3f3f3f3f #define pi acos(-1.0) #define LL long long #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 //#define mp make_pair #define pb push_back #define ULL unsigned LL #define mem(a, b) memset(a, b, sizeof(a)) #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) //#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); const int maxn = 1100; int mark[maxn]; vector<int> v[maxn]; int n, ans; void init (){ mem(mark, 0); for (int i = 0; i <= n; ++i) v[i].clear(); ans = 1; } void dfs(int start, int End, int tag){ if (!ans)//已經知道答案了 快速返回 return; //標記該人關係 mark[start] = tag; for (int i = 0; i < v[start].size(); ++i){ int ter = v[start][i]; //不走回頭路 if (ter == End) continue; //如果發現每段 不是對立的關係 if (mark[ter] == tag){ ans = 0; return; } //注意這裡 不能直接else 不然就會一直迴圈 比如1 3 5 4 1 3 5 4 1 一直重複 沒確定關係才去dfs else if (!mark[ter]){ dfs(ter, start, -tag); } } } int main(){ int m, x, y; while (~scanf("%d%d%d%d", &n, &m, &x, &y)){ init(); int a, b; for (int i = 0; i < m; ++i){ scanf("%d%d", &a, &b); v[a].push_back(b); v[b].push_back(a); } int people; //標記好人 壞人 for (int i = 0; i < x; ++i){ scanf("%d", &people); mark[people] = 1; } for (int i = 0; i < y; ++i){ scanf("%d", &people); mark[people] = -1; } //因為圖可能不是連通的 有多個連通快 //根據已經確定關係的 進而確定對立那個 for (int i = 1; i <= n; ++i){ //0是沒確定關係的 if (mark[i] && v[i].size() >= 1){ //利用了0 是不存在 這樣dfs i點就會把i這裡面整個連通塊跑完 確定好裡面的關係 dfs(i, 0, mark[i]); } } //可能存在 還有一些連通快沒有確定關係 for (int i = 1; i <= n; ++i){ if (!mark[i] && v[i].size()){ dfs(i, 0, 1);//隨便給 假定是好人 } } //這樣就把那些連通快(起碼兩個點)都確定了 //如果仍有沒確定的 那這些就是單個點 作為一個連通快 那他可以好人 可以壞人 輸出NO for (int i = 1; i <= n; ++i){ if (!mark[i]){ ans = 0; break; } } if (ans) printf("YES\n"); else printf("NO\n"); } }