1. 程式人生 > >2018-2019 ICPC, NEERC(CF 1071I) Privatization of Roads in Berland

2018-2019 ICPC, NEERC(CF 1071I) Privatization of Roads in Berland

題目:

n個點m條邊,無窮多個公司,給每個公司最多分配兩條邊,每條邊都要被分配出去,且每個點相連的所有的邊所屬的公司數不超過k。輸出一種邊分配方案。

分析:

記錄每個點的度數,如果一個點的度數d[i] <= k,那麼這個點相連的邊無需合併,可直接給每個邊分配一個公司(因為公司有無窮多個)
如果一個點的度數d[i] > k,那麼這個點的邊至少要合併 2*(d[i]-k)條,而每條邊只能被合併一次。這樣便可最大流判定是否有解,源點S向每個城市點建流量為max(0, 2*(d[i]-k))的邊,城市點向對應的道路點連容量為1的邊,每個道路點向匯點T建立容量為1的邊。

程式碼:

#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 1205;
const int MAXM = 5005;
const int INF = 0x3f3f3f3f;
struct Edge {
	int to, next, cap, flow;
} edge[MAXM];
int tot, head[MAXN];
int Q[MAXN], cur[MAXN], dep[MAXN];
int n, m, S, T, N, to[MAXN];
void init() {
	tot = 2;
	memset(head, -1, sizeof head);
}
void addedge(int u, int v, int w, int rw = 0) {
	edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
	edge[tot].next = head[u]; head[u] = tot++;
	edge[tot].to = u; edge[tot].cap = rw; edge[tot].flow = 0;
	edge[tot].next = head[v]; head[v] = tot++;
}
bool bfs(int s, int t, int n) {
	int Front = 0, tail = 0;
	memset(dep, -1, sizeof(dep[0]) * (n + 1));
	dep[s] = 0;
	Q[tail++] = s;
	while (Front < tail) {
		int u = Q[Front++];
		for (int i = head[u]; i != -1; i = edge[i].next) {
			int v = edge[i].to;
			if (edge[i].cap > edge[i].flow && dep[v] == -1) {
				dep[v] = dep[u] + 1;
				if (v == t) return true;
				Q[tail++] = v;
			}
		}
	}
	return false;
}
int dfs(int u, int f) {
	if (u == T)	return f;
	int used = 0, rflow = 0;
	for (int i = cur[u]; i != -1; i = edge[i].next) {
		cur[u] = i;
		int v = edge[i].to, w = edge[i].cap - edge[i].flow;
		if (w > 0 && dep[v] == dep[u] + 1) {
			if ((rflow = dfs(v, min(w, f - used)))) {
				used += rflow;
				edge[i].flow += rflow;
				edge[i ^ 1].flow -= rflow;
				if (used == f)	break;
			}
		}
	}
	if (!used)	dep[u] = -1;
	return used;
}
int dinic(int s, int t, int n) {
	int maxflow = 0;
	while (bfs(s, t, n)) {
		for (int i = 0; i <= n; i++)	cur[i] = head[i];
		maxflow += dfs(s, INF);
	}
	return maxflow;
}
int col[MAXN], d[MAXN], k;
int main() {
	freopen("1.txt","r",stdin);
	ios::sync_with_stdio(false);
	int kase;
	cin >> kase;
	while (kase--) {
		cin >> n >> m >> k;
		init();
		S = 0, T = n + m + 1, N = n + m + 1;
		for (int i = 0; i <= max(n,m); i++) d[i] = 0, col[i] = 0;
		for (int i = 1; i <= m; i++) {
			int a, b; cin >> a >> b;
			d[a]++, d[b]++;
			addedge(a, n + i, 1); addedge(b, n + i, 1);
			addedge(n + i, T, 1);
		}
		int sum = 0;
		for (int i = 1; i <= n; i++) {
			if (d[i] > k) {
				addedge(S, i, 2 * (d[i] - k));
				sum += 2 * (d[i] - k); 
			}
		}
		if (sum == dinic(S, T, N)) {
			int now = 0;
			vector<int> tp;
			for(int i=1;i<=n;i++) {
				for(int k=head[i];k!=-1;k=edge[k].next) {
					if(edge[k].flow == 1)	tp.push_back(edge[k].to);
				}
			}
			for(int i=0;i<(int)tp.size();i+=2){
				col[tp[i]-n] = col[tp[i+1]-n] = ++now;
			}
			for(int i=1;i<=m;i++) if(col[i] == 0) col[i] = ++now;
		} 
		for (int i = 1; i <= m; i++) cout << col[i] << " \n"[i == m];
	}
	return 0;
}

相關推薦

2018-2019 ICPC, NEERC(CF 1071I) Privatization of Roads in Berland

題目: n個點m條邊,無窮多個公司,給每個公司最多分配兩條邊,每條邊都要被分配出去,且每個點相連的所有的邊所屬的公司數不超過k。輸出一種邊分配方案。 分析: 記錄每個點的度數,如果一個點的度數d[i] <= k,那麼這個點相連的邊無需合併,可直接給每個邊分

CF 1070I Privatization of Roads in Berland 網路流

題意: 給你一個無向圖,每條邊連線兩個城市,現在要給每條邊分配一個顏色,每個顏色不能被用超過兩次, 每個城市最多被k種顏色連,問是否存在,輸出方案。 題解: 設一個城市和deg[i]條邊相連,如果deg[i] > k, 那麼起碼要把2 * (deg[i] -

codeforces 1070I 2018-2019 ICPC,NEERC,Southern Subregional Contest Privatization of Roads in Berlan

題面 題意 給出一張無向圖,現在要對上面的邊進行染色(可以認為有無數種顏色),並且每種邊只能染一種顏色,每種顏色最多隻能染兩條邊,並且與每個點相連的邊最多隻有k種顏色,請輸出一種方案。 做法 首先如果存在一個度數大於

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution

從這裡開始 題目列表 瞎扯 Problem A Find a Number Problem B Berkomnadzor Problem C Cloud Computing Problem D Garbage Disp

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) 體驗記

  原文連結https://www.cnblogs.com/zhouzhendong/p/CF1070.html 比賽網址:http://codeforces.com/contest/1070 感受   本來只打算玩玩的。   結果玩的海星。   我做 A 題的時候可能比較浮躁吧,各種傻

【*2000】【2018-2019 ICPC, NEERC, Southern Subregional Contest C 】Cloud Computing

【連結】 我是連結,點我呀:) 【題意】 【題解】 我們可以很容易知道區間的每個位置有哪些安排可以用。 顯然 我們優先用那些花費的錢比較少的租用cpu方案。 但一個方案可供租用的cpu有限。 我們可以用一個線段樹 線段樹的下標表示價格。 那一位的值,為這個價格的cpu能租多少個。 弄

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

  A. Find a Number   找到一個樹,可以被d整除,且數字和為s   記憶化搜尋   1 static class S{ 2 int mod,s; 3 String str; 4 5

Codeforces 1070C - Cloud Computing 思路+線段樹+貪心 (2018-2019 ICPC, NEERC)

CF:*2000   題意: 有n天,每天需要用k個cpu,  然後給定m個計劃,對於每個計劃包含 L, R, c, p 表示,從第L天到第R天期間,每天你都可以選用c個cpu,每個cpu的花費為p; 問n天的最小花費;(當

Codeforces 1070H - BerOS File Suggestion 暴力 (2018-2019 ICPC, NEERC)

CF: *1600   題意:給定n個字串(長度最大8),q個查詢,問上述n個串中有多少個串的子串是這個查詢的串,任意輸出一個原串 思路:直接暴力   #include<bits/stdc++.h> using namespace std;

2018-2019 ICPC, NEERC, Southern Subregional Contest J-Streets and Avenues in Berhatt [contest/1070]

J - Streets and Avenues in Berhatt 題面 思路 簡單猜測可知,貢獻答案的情況下必然是一組相同的字母被分割在橫豎兩個方向,其餘的都不會貢獻答案 因為我們可以用把一組字母儘量用完的方式優先放一橫或者一豎,排完之後會有兩種情況

2018-2019 ICPC, NEERC, Southern Subregional Contest B - Berkomnadzor [contest/1070]

B - Berkomnadzor [contest/1070] 題面 思路 考慮二進位制,遮蔽只是不影響後 32 −

2018-2019 ICPC, NEERC, Southern Subregional Contest C - Cloud Computing [contest/1070]

C - Cloud Computing [contest/1070] 題面 思路 考慮維護一個 c [

2018-2019 ICPC, NEERC, Southern Subregional Contest 部分題解

A. Find a Number 思路:從0開始bfs搜尋就好了,直到模數等於0且數字和等於s就好了。   #include<cstdio> #include<iostream> #include<cstring> #include<

Codeforces 1089E - Easy Chess - [DFS+特判][2018-2019 ICPC, NEERC, Northern Eurasia Finals Problem E]

題目連結:https://codeforces.com/contest/1089/problem/E Elma is learning chess figures. She learned that a rook can move either horizontally or vertically. To

記第一場atcoder和codeforces 2018-2019 ICPC, NEERC, Northern Eurasia Finals Online Mirror

下午連著兩場比賽,爽。 首先是codeforses,我和一位dalao一起打的,結果考炸了,幸虧不計rating。。 A Alice the Fan 這個就是記憶化搜尋一下預處理,然後直接回答詢問好了,我肯定是傻逼了,還寫了這麼長,幸虧調處來了。 #include<cstdio> #i

2018-2019 ICPC, NEERC, Northern Eurasia Finals

地址 Rank Solved A B C D E F G H I J K L M 183/815 5/13 O

2018-2019 ICPC, NEERC, Northern Eurasia Finals (Unrated, Online Mirror, ICPC Rules, Teams Preferred) Solution

A. Alice the Fan Solved. 題意: 兩個人打網球,要求teamA 的得分與其他隊伍拉開儘量大 輸出合法的方案 思路:  $dp[i][j][k][l] 表示 A 贏i局,其他隊伍贏j局,兩個人比分為k : l 的時候的方案$ 1 #inc

2018-2019 ICPC, NEERC, Southern Subregional Contest:A. Find a Number(BFS)

A. Find a Number time limit per test 3 seconds memory limit per test 256 megabytes inputstandard inpu

10月20日 訓練記錄 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Team

A題 題意:求數位總和為s且是d的倍數的最小值,若無解輸出-1 思路:s<=5000,d<=500說明狀態數<=s*d=5000*500,bfs搜尋 程式碼: #include<bits/stdc++.h> using namespace