传送门:点击打开链接
题意:一个无向图中,每条边可能是0或者1。有一种对节点u的操作,操作时把节点u连接的所有边的权值0变1,1变0.现在要把所有边的权值边成相等的,问最少的操作步数,并打印方案。
思路:如果确定最后边的颜色了,并对所有的连通块中,确定了一个节点的颜色,那么整个连通块的操作节点就是唯一确定的了。
打印方案比较麻烦,,慢慢debug。。
#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; const int MX = 1e5 + 5; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; struct Ans { bool ok; vector<int>s; bool operator<(const Ans &P)const { if(ok == P.ok) return s.size() < P.s.size(); return ok > P.ok; } }; int n, m; struct Edge { int v, nxt, z; } E[MX << 2]; int Head[MX], erear; void edge_init() { erear = 0; memset(Head, -1, sizeof(Head)); } void edge_add(int u, int v, int z) { E[erear].v = v; E[erear].z = z; E[erear].nxt = Head[u]; Head[u] = erear++; } int col[MX], vis[MX]; Ans deal(int x, int u, int c) { Ans ret; ret.ok = true; vector<int> p; queue<int> Q; Q.push(u); col[u] = c; vis[u] = 1; p.push_back(u); while(!Q.empty()) { u = Q.front(); Q.pop(); if(col[u]) ret.s.push_back(u); for(int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if(vis[v] && (col[u]^col[v]^E[i].z) != x) { ret.ok = false; break; } if(!vis[v]) { col[v] = E[i].z ^ col[u] ^ x; vis[v] = 1; Q.push(v); p.push_back(v); } } } if(c == 0) { for(int i = 0; i < p.size(); i++) { vis[p[i]] = 0; } } return ret; } Ans solve(int x) { Ans ret, temp; memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) { if(vis[i]) continue; temp = min(deal(x, i, 1), deal(x, i, 0)); if(!temp.ok) { ret.ok = false; return ret; } for(int j = 0; j < temp.s.size(); j++) { ret.s.push_back(temp.s[j]); } } ret.ok = true; return ret; } int main() { edge_init(); //FIN; scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) { int u, v; char op[10]; scanf("%d%d%s", &u, &v, op); int z = op[0] == 'R' ? 1 : 0; edge_add(u, v, z); edge_add(v, u, z); } Ans ans = min(solve(0), solve(1)); if(!ans.ok) printf("-1\n"); else { int sz = ans.s.size(); printf("%d\n", sz); for(int i = 0; i < sz; i++) { printf("%d%c", ans.s[i], i == sz - 1 ? '\n' : ' '); } } return 0; }