hdu 4975 A simple Gaussian elimination problem 最大流+找环
原题链接
http://acm.hdu.edu.cn/showproblem.php?pid=4975
这是一道很裸的最大流,将每个点(i,j)看作是从Ri向Cj的一条容量为9的边,从源点除法连接每个Ri,再从每个Ci连接至汇点。如若最大流不是滿流,则问题无解。这道题的关键就是在于如何判断是否有多解。考虑这样一个事实,若残余网络上有多个点构成一个环,那么流量可在这个环上调整,某条边上多余的流量可以被环上的其他的边弥补回来。所以如果残余网络上存在一个边数大于2的环,那么问题则是多解。我判断是否有环的方法是Tarjan。
详见代码:
- #include<iostream>
- #include<stack>
- #include<vector>
- #include<cstring>
- #include<algorithm>
- #include<queue>
- #define MAX_V 2015
- #define MAX_N 10004
- #define INF 2500005
- using namespace std;
- struct edge{int to,cap,rev;};
- vector<edge> G[MAX_N];
- int level[MAX_V];
- int iter[MAX_V];
- void add_edge(int from,int to,int cap) {
- G[from].push_back((edge) {to, cap, G[to].size()});
- G[to].push_back((edge) {from, , G[from].size() - });
- }
- void bfs(int s) {
- memset(level, -, sizeof(level));
- queue<int> que;
- level[s] = ;
- que.push(s);
- while (!que.empty()) {
- int v = que.front();
- que.pop();
- for (int i = ; i < G[v].size(); i++) {
- edge &e = G[v][i];
- if (e.cap > && level[e.to] < ) {
- level[e.to] = level[v] + ;
- que.push(e.to);
- }
- }
- }
- }
- int dfs(int v,int t,int f) {
- if (v == t)return f;
- for (int &i = iter[v]; i < G[v].size(); i++) {
- edge &e = G[v][i];
- if (e.cap > && level[v] < level[e.to]) {
- int d = dfs(e.to, t, min(f, e.cap));
- if (d > ) {
- e.cap -= d;
- G[e.to][e.rev].cap += d;
- return d;
- }
- }
- }
- return ;
- }
- int max_flow(int s,int t) {
- int flow = ;
- for (; ;) {
- bfs(s);
- if (level[t] < )return flow;
- memset(iter, , sizeof(iter));
- int f;
- while ((f = dfs(s, t, INF)) > ) {
- flow += f;
- }
- }
- }
- bool vis[MAX_N];
- int low[MAX_N],dfn[MAX_N],tot=;
- bool inStack[MAX_N];
- stack<int> st;
- bool exitCircle=false;
- void Tarjan(int u) {
- if (exitCircle)return;
- vis[u] = ;
- inStack[u] = ;
- st.push(u);
- low[u] = dfn[u] = ++tot;
- for (int i = ; i < G[u].size(); i++) {
- int v = G[u][i].to;
- if (G[u][i].cap == )continue;
- if (!vis[v]) {
- Tarjan(v);
- low[u] = min(low[u], low[v]);
- }
- else if (inStack[v])
- low[u] = min(low[u], dfn[v]);
- }
- if (dfn[u] == low[u]) {
- int cnt = ;
- while (inStack[u]) {
- if (st.empty())break;
- cnt++;
- //cout << st.top() << " ";
- inStack[st.top()] = ;
- st.pop();
- }
- if (cnt > )exitCircle = true;
- //cout << endl;
- }
- }
- int T;
- int N,M;
- int main() {
- cin.sync_with_stdio(false);
- cin >> T;
- int cas = ;
- while (T--) {
- int sum = ;
- cin >> N >> M;
- for(int i=;i<N+M+;i++)G[i].clear();
- memset(vis,,sizeof(vis));
- memset(dfn,,sizeof(dfn));
- memset(low,,sizeof(low));
- tot=;
- memset(inStack,,sizeof(inStack));
- exitCircle=false;
- while(st.size())st.pop();
- for (int i = ; i < N; i++) {
- int a;
- cin >> a;
- sum += a;
- add_edge(, i + , a);
- }
- for (int i = ; i < M; i++) {
- int a;
- cin >> a;
- add_edge(N + i + , N + M + , a);
- }
- for (int i = ; i <= N; i++)
- for (int j = ; j <= M; j++)
- add_edge(i, j + N, );
- int flow = max_flow(, N + M + );
- cout << "Case #" << ++cas << ": ";
- if (flow != sum) {
- cout << "So naive!" << endl;
- continue;
- }
- for (int i = ; i <= N + M + ; i++)if (!vis[i])Tarjan(i);
- if (exitCircle)cout << "So young!" << endl;
- else cout << "So simple!" << endl;
- }
- return ;
- }
hdu 4975 A simple Gaussian elimination problem 最大流+找环的更多相关文章
- HDU 4975 A simple Gaussian elimination problem.
A simple Gaussian elimination problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be ...
- hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One ...
- hdu - 4975 - A simple Gaussian elimination problem.(最大流量)
意甲冠军:要在N好M行和列以及列的数字矩阵和,每个元件的尺寸不超过9,询问是否有这样的矩阵,是独一无二的N(1 ≤ N ≤ 500) , M(1 ≤ M ≤ 500). 主题链接:http://acm ...
- HDOJ 4975 A simple Gaussian elimination problem.
和HDOJ4888是一样的问题,最大流推断多解 1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉...... 2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開 ...
- hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)
这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...
- A simple Gaussian elimination problem.(hdu4975)网络流+最大流
A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...
- A simple Gaussian elimination problem.
hdu4975:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:给你一个n*m的矩阵,矩阵中的元素都是0--9,现在给你这个矩阵的每一行和每一列的和 ...
- hdu4975 A simple Gaussian elimination problem.(最大流+判环)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:和hdu4888基本一样( http://www.cnblogs.com/a-clown/ ...
- hdu 4972 A simple dynamic programming problem(高效)
pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...
随机推荐
- python-DB模块实例
MySQLdb其实有点像php或asp中连接数据库的一个模式了,只是MySQLdb是针对mysql连接了接口,我们可以在python中连接MySQLdb来实现数据的各种操作. python连接mysq ...
- 人脸识别源代码Open cv
#include <stdio.h> #include <string.h> #include "cv.h" #include "cvaux.h& ...
- Springboot(二)-application.yml默认的配置项以及读取自定义配置
写在前面 ===== spring-boot 版本:2.0.0.RELEASE ===== 读取自定义配置 1.配置文件:sys.properties supply.place=云南 supply.c ...
- 使用Hexo+Github搭建属于自己的博客
工具:Visual Studio Code/MarkdownPad技术:Hexo+Github 创建Github项目 Github账户注册和新建项目,项目必须要遵守格式:账户名.github.io,不 ...
- 【支付宝支付】扫码付和app支付,回调验证签名失败问题
在检查了参数排序,编码解码,文件编码等问题后,发现还是签名失败,最后找出原因: 扫码付和app支付采用的支付宝公钥不一样 Pid和公钥管理里面: 开放平台密钥界面和开放平台应用界面的密钥应该一 ...
- 面试Python工程师,这几道编码题有必要背背,Python面试题No8
第1题:列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]. map是python高阶用法,字面意义是映射,它的 ...
- Python9-反射-day27(大年初三)
复习 class 类名(父类,父类2): 静态属性 = '' #静态属性 类属性 def __init__(self): #初始化方法 self.name = 'alex' def func(self ...
- 00037_this关键字
1.成员变量和局部变量同名问题 当在方法中出现了局部变量和成员变量同名的时候,可以在成员变量名前面加上this.来区别成员变量和局部变量. class Person { private int age ...
- python基础-面向对象(装饰器)
属性: @property @method_name.setter @method_name.deleter 三个标签都是放在方法的上面来使用,且方法名要和后续使用的 变量名字相一 ...
- Leetcode 365.水壶问题
水壶问题 有两个容量分别为 x升和 y升的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. 你允许: 装满 ...