[hdu4888]最大流,判断最大流唯一性
题意:给一个n*m的矩形,往每个格子填0-k的数字,使得对第i行和为row[i],第i列和为col[i],问是否存在方案,方案是否唯一,如果方案唯一则输出具体方案。
思路:首先根据问题提取对象,行、列、格子、数,只有数可以连接其它的对象。从源点向第i行连一条容量为row[i]的有向边,从第i行向第i行的每个格子连一条容量为k的有向边,从每个格子向第i列(i为格子的列号)连一条容量为k的有向边,然后从第i列向汇点连一条容量为col[i]的边。这样建图以后,发现每个格子唯一连接一个行和一个列,也就是入度和出度均为1,那么格子其实就没有存在的必要了,直接从每行向每列连一条容量为k的有向边。如果最大流=Σrow[i]=Σcol[i],则表明有解。对于有多解的情况,只需判断残量网络是否存在有向环,因为在环上增减流量能得到不同的解而最大流不变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
/* ******************************************************************************** */ #include <iostream> // #include <cstdio> // #include <cmath> // #include <cstdlib> // #include <cstring> // #include <vector> // #include <ctime> // #include <deque> // #include <queue> // #include <algorithm> // #include <map> // using namespace std; // // #define pb push_back // #define mp make_pair // #define X first // #define Y second // #define all(a) (a).begin(), (a).end() // #define foreach(a, i) for (typeof(a.begin()) i = a.begin(); i != a.end(); ++ i) // #define fill(a, x) memset(a, x, sizeof(a)) // // void RI(vector< int >&a, int n){a.resize(n); for ( int i=0;i<n;i++) scanf ( "%d" ,&a[i]);} // void RI(){} void RI( int &X){ scanf ( "%d" ,&X);} template < typename ...R> // void RI( int &f,R&...r){RI(f);RI(r...);} void RI( int *p, int *q){ int d=p<q?1:-1; // while (p!=q){ scanf ( "%d" ,p);p+=d;}} void print(){cout<<endl;} template < typename T> // void print( const T t){cout<<t<<endl;} template < typename F, typename ...R> // void print( const F f, const R...r){cout<<f<< ", " ;print(r...);} template < typename T> // void print(T*p, T*q){ int d=p<q?1:-1; while (p!=q){cout<<*p<< ", " ;p+=d;}cout<<endl;} // // typedef pair< int , int > pii; // typedef long long ll; // typedef unsigned long long ull; // // template < typename T> bool umax(T&a, const T&b){ return b>a? false :(a=b, true );} // template < typename T> bool umin(T&a, const T&b){ return b<a? false :(a=b, true );} // template < typename T> // void V2A(T a[], const vector<T>&b){ for ( int i=0;i<b.size();i++)a[i]=b[i];} // template < typename T> // void A2V(vector<T>&a, const T b[]){ for ( int i=0;i<a.size();i++)a[i]=b[i];} // // /* -------------------------------------------------------------------------------- */ struct Dinic { private : const static int maxn = 800 + 7; struct Edge { int from, to, cap; Edge( int u, int v, int w): from(u), to(v), cap(w) {} }; int s, t; vector<Edge> edges; vector< int > G[maxn]; bool vis[maxn]; int d[maxn], cur[maxn]; bool bfs() { memset (vis, 0, sizeof (vis)); queue< int > Q; Q.push(s); d[s] = 0; vis[s] = true ; while (!Q.empty()) { int x = Q.front(); Q.pop(); for ( int i = 0; i < G[x].size(); i ++) { Edge &e = edges[G[x][i]]; if (!vis[e.to] && e.cap) { vis[e.to] = true ; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int dfs( int x, int a) { if (x == t || a == 0) return a; int flow = 0, f; for ( int &i = cur[x]; i < G[x].size(); i ++) { Edge &e = edges[G[x][i]]; if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap))) > 0) { e.cap -= f; edges[G[x][i] ^ 1].cap += f; flow += f; a -= f; if (a == 0) break ; } } return flow; } public : void clear() { for ( int i = 0; i < maxn; i ++) G[i].clear(); edges.clear(); memset (d, 0, sizeof (d)); } void add( int from, int to, int cap) { edges.push_back(Edge(from, to, cap)); edges.push_back(Edge(to, from, 0)); int m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } int solve( int s, int t) { this ->s = s; this ->t = t; int flow = 0; while (bfs()) { memset (cur, 0, sizeof (cur)); flow += dfs(s, 1e9); } return flow; } bool FC( int fa, int rt) { vis[rt] = true ; int sz = G[rt].size(); for ( int i = 0; i < sz; i ++) { Edge &e = edges[G[rt][i]]; if (e.to != fa && e.cap) { if (vis[e.to]) return true ; if (FC(rt, e.to)) return true ; } } vis[rt] = false ; return false ; } bool get( int n, int m) { memset (vis, 0, sizeof (vis)); for ( int i = 1; i <= n; i ++) { if (FC(-1, i)) return true ; } return false ; } void out( int n, int m) { int now = n * 2 + m * 2 + 1; for ( int i = 0; i < n; i ++) { for ( int j = 0; j < m; j ++) { printf ( "%d%c" , edges[now].cap, j == m - 1? '\n' : ' ' ); now += 2; } } } }; Dinic solver; const int maxn = 407; int row[maxn], col[maxn]; int main() { #ifndef ONLINE_JUDGE freopen ( "in.txt" , "r" , stdin); #endif // ONLINE_JUDGE int n, m, k; while (cin >> n >> m >> k) { solver.clear(); int total = 0; for ( int i = 1; i <= n; i ++) { int x; RI(x); solver.add(0, i, x); total += x; } for ( int i = 1; i <= m; i ++) { int x; RI(x); solver.add(n + i, n + m + 1, x); } for ( int i = 1; i <= n; i ++) { for ( int j = 1; j <= m; j ++) { solver.add(i, n + j, k); } } int flow = solver.solve(0, n + m + 1); if (flow != total) puts ( "Impossible" ); else { if (solver.get(n, m)) puts ( "Not Unique" ); else { puts ( "Unique" ); solver.out(n, m); } } } return 0; // } // // // // /* ******************************************************************************** */ |
[hdu4888]最大流,判断最大流唯一性的更多相关文章
- HDU 3572 Task Schedule(最大流判断满流)
https://vjudge.net/problem/HDU-3572 题意: 有N个作业和M台机器,每个作业都有一个持续时间P,工作的日期为S~E.作业可以断断续续的在不同机器上做,每台机器每次只可 ...
- HDU2883 kebab(最大流判断满流 + 离散化 + 区间化点)
[题意]: 有一个烤箱,烤箱在一个时刻最多考M个肉串,N个顾客,每个顾客有属性s,n,e,t s是来的时间,n是想要的肉串数量,e是最晚离开的时间,t是烤的时间(几分熟). 顾客的烤肉可以分开烤,比如 ...
- hdu-3572 Task Schedule---最大流判断满流+dinic算法
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3572 题目大意: 给N个任务,M台机器.每个任务有最早才能开始做的时间S,deadline E,和持 ...
- hdu3572 任务分配/最大流判断满流
题意:将n个任务分配为m个机器,给每个任务需要的天数(无需每天连续),和可以在哪些天去做该任务,求是否存在方案. 典型的任务(X)----天(Y)二分最大流,(因为这里任务是与天的关系)处理器控制流量 ...
- hdu 3572 最大流判断满流
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define ...
- hdu4888 多校B 最大流以及最大流唯一判断+输出方案
题意,给一个矩阵,告诉你每行和.每列和,并且限制所填数不大于k,问矩阵是否唯一. 经典建图不说了,第一次遇到判断最大流唯一性的,学习了:用dfs来判断残网中是否还存在环,若存在,则表明绕这个环走一圈, ...
- hdu3572Task Schedule 最大流,判断满流 优化的SAP算法
PS:多校联赛的题目质量还是挺高的.建图不会啊,看了题解才会的. 参考博客:http://blog.csdn.net/luyuncheng/article/details/7944417 看了上面博客 ...
- EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案之使用RTSP流判断摄像机设备是否在线以及快照抓取
背景分析 熟知EasyNVR产品的小伙伴都知道,通过纯Web化的交互方式,只要配置出摄像机的IP.端口.用户名.密码等信息,就可以将地址进行通道配置完成,即可将设备接入.如果设备支持Onvif协议,E ...
- hdu4940 有上下界的无源可行流判断
题意: 给你一个强连通图,然后问你是否可以找到任意满足条件的集合S,S是非空集合,T是S的补集,满足sum(D[i ,j]) <= sum(D[j,i] + B[j,i]) i属于S ...
- POJ3189二分最大流(枚举下界,二分宽度,最大流判断可行性)
题意: 有n头猪,m个猪圈,每个猪圈都有一定的容量(就是最多能装多少只猪),然后每只猪对每个猪圈的喜好度不同(就是所有猪圈在每个猪心中都有一个排名),然后要求所有的猪都进猪圈,但是要求所有 ...
随机推荐
- Laravel - 基础
1.使用 composer 创建项目 composer create-project --prefer-dist laravel/laravel blog 报错1 [ErrorException]pr ...
- 功能测试--聊天功能测试&微信聊天
微信聊天功能测试 发送对象 普通用户.公众号.群.其他特殊主体 衍生功能 转发.语音转文字.删除等 消息发送 单聊.群聊.语音.文字.图片.表情.链接.字符及长度 消息管理 发布通知.接受通知.发文件 ...
- tp5--相对路径和绝对路径
首先,我们要先明白相对路径和绝对路径的理论: 绝对路径:是从盘符开始的路径,形如C:\windows\system32\cmd.exe相对路径:是从当前路径开始的路径,假如当前路径为C:\window ...
- json格式的相互转化
直接上代码: header("Content-type: text/html; charset=utf-8"); $arr = array(); $arr = [ ', ', ' ...
- 作业九——DFA最小化,语法分析初步
- java中Locks的使用
文章目录 Lock和Synchronized Block的区别 Lock interface ReentrantLock ReentrantReadWriteLock StampedLock Cond ...
- js 实现动画功能,完整解析插件版 可更改配置参数[animate.js]
前言: 本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽. 本篇文章为您分析一下原生JS写一个运动插件 基本功能: 补充 ...
- XML--XML从入门到精通 Part 1 认识XML
XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 标签没有被预定义.您需要 ...
- ACM一年记,总结报告(希望自己可以走得很远)
一. 知识点梳理 (一) 先从工具STL说起: 容器学习了:stack,queue,priority_queue,set/multiset,map/multimap,vector. 1.stack: ...
- The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)
This is an era of team success, but also an era of heroes. Throughout the ages, there have been nume ...