CF 1070I Privatization of Roads in Berland 網路流
阿新 • • 發佈:2018-12-16
題意:
給你一個無向圖,每條邊連線兩個城市,現在要給每條邊分配一個顏色,每個顏色不能被用超過兩次, 每個城市最多被k種顏色連,問是否存在,輸出方案。
題解:
設一個城市和deg[i]條邊相連,如果deg[i] > k, 那麼起碼要把2 * (deg[i] - k)條邊兩兩合併成同一顏色。
對於所有城市i 連所有和他相連的邊,容量為1。
如果deg[i] > k, 那麼源點連 i 容量為 2 * (deg[i] - k)。
對於所有邊連匯點容量為1,代表只能被合併一次。
跑網路流看是否是最大流。
最後看邊是否有流量,同一個城市連的邊中兩兩任意合併。
程式碼:
#include <bits/stdc++.h> #ifdef LOCAL #define debug(x) cout<<#x<<" = "<<(x)<<endl; #else #define debug(x) 1; #endif #define chmax(x,y) x=max(x,y) #define chmin(x,y) x=min(x,y) #define lson id<<1,l,mid #define rson id<<1|1,mid+1,r #define lowbit(x) x&-x #define mp make_pair #define rep(i,a,b) for(int i=a;i<b;i++) #define pb push_back #define fir first #define sec second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int MOD = 1e9 + 7; const double PI = acos (-1.); const double eps = 1e-10; const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3f; const int MAXN = 1e6 + 5; const int inf = 0x3f3f3f3f; const int MX = 2222; const int MXE = 4 * MX * MX; struct MaxFlow { struct Edge { int v, w, nxt; } edge[MXE]; int tot, num, s, t; int head[MX]; void init() { memset(head, -1, sizeof(head)); tot = 0; } void add(int u, int v, int w) { edge[tot].v = v; edge[tot].w = w; edge[tot].nxt = head[u]; head[u] = tot++; edge[tot].v = u; edge[tot].w = 0; edge[tot].nxt = head[v]; head[v] = tot++; } int d[MX], vis[MX], gap[MX]; void bfs() { memset(d, 0, sizeof(d)); memset(gap, 0, sizeof(gap)); memset(vis, 0, sizeof(vis)); queue<int>q; q.push(t); vis[t] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = edge[i].nxt) { int v = edge[i].v; if (!vis[v]) { d[v] = d[u] + 1; gap[d[v]]++; q.push(v); vis[v] = 1; } } } } int last[MX]; int dfs(int u, int f) { if (u == t) return f; int sap = 0; for (int i = last[u]; ~i; i = edge[i].nxt) { int v = edge[i].v; if (edge[i].w > 0 && d[u] == d[v] + 1) { last[u] = i; int tmp = dfs(v, min(f - sap, edge[i].w)); edge[i].w -= tmp; edge[i ^ 1].w += tmp; sap += tmp; if (sap == f) return sap; } } if (d[s] >= num) return sap; if (!(--gap[d[u]])) d[s] = num; ++gap[++d[u]]; last[u] = head[u]; return sap; } int solve(int st, int ed, int n) { int flow = 0; num = n; s = st; t = ed; bfs(); memcpy(last, head, sizeof(head)); while (d[s] < num) flow += dfs(s, inf); return flow; } } F; int deg[MAXN]; int col[MAXN]; vector <int> G[666]; int main() { #ifdef LOCAL freopen ("input.txt", "r", stdin); #endif int T; cin >> T; while (T--) { int n, m, k; scanf ("%d %d %d", &n, &m, &k); F.init(); for (int i = 1; i <= n; i++) { G[i].clear(); deg[i] = 0; } int st = 0, en = n + m + 1, f = 0; for (int i = 1; i <= m; i++) { int x, y; scanf ("%d %d", &x, &y); deg[x]++; deg[y]++; F.add (x, i + n, 1); G[x].pb (F.tot - 1); F.add (y, i + n, 1); G[y].pb (F.tot - 1); F.add (i + n, en, 1); col[i] = 0; } int ok = 1; for (int i = 1; i <= n; i++) { if (deg[i] > 2 * k) ok = 0; if (deg[i] > k) F.add (st, i, 2 * (deg[i] - k)), f += 2 * (deg[i] - k); } if (!ok || f != F.solve(st, en, en + 5)) { for (int i = 1; i <= m; i++) printf ("0 "); puts(""); } else { int tot = 0; for (int i = 1; i <= n; i++) { vector <int> v; for (int j : G[i]) if (F.edge[j].w) v.pb (j); if (v.size()) for (int j = 1; j < v.size(); j += 2) { col[F.edge[v[j]^1].v - n] = col[F.edge[v[j-1]^1].v - n] = ++tot; } } for (int i = 1; i <= m; i++) { if (!col[i]) col[i] = ++tot; printf ("%d ", col[i]); } puts (""); } } return 0; }