原题链接

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 最大流+找环的更多相关文章

  1. HDU 4975 A simple Gaussian elimination problem.

    A simple Gaussian elimination problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be ...

  2. hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One ...

  3. hdu - 4975 - A simple Gaussian elimination problem.(最大流量)

    意甲冠军:要在N好M行和列以及列的数字矩阵和,每个元件的尺寸不超过9,询问是否有这样的矩阵,是独一无二的N(1 ≤ N ≤ 500) , M(1 ≤ M ≤ 500). 主题链接:http://acm ...

  4. HDOJ 4975 A simple Gaussian elimination problem.

    和HDOJ4888是一样的问题,最大流推断多解 1.把ISAP卡的根本出不来结果,仅仅能把全为0或者全为满流的给特判掉...... 2.在残量网络中找大于2的圈要用一种类似tarjian的方法从汇点開 ...

  5. hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)

    这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...

  6. A simple Gaussian elimination problem.(hdu4975)网络流+最大流

    A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65 ...

  7. A simple Gaussian elimination problem.

    hdu4975:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:给你一个n*m的矩阵,矩阵中的元素都是0--9,现在给你这个矩阵的每一行和每一列的和 ...

  8. hdu4975 A simple Gaussian elimination problem.(最大流+判环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 题意:和hdu4888基本一样( http://www.cnblogs.com/a-clown/ ...

  9. hdu 4972 A simple dynamic programming problem(高效)

    pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...

随机推荐

  1. java script DOM BOM

    onclick        当用户点击某个对象时调用的事件句柄.ondblclick     当用户双击某个对象时调用的事件句柄. onfocus        元素获得焦点.            ...

  2. SSI的实例(登录增删改查)

    源码下载:http://download.csdn.net/detail/u011518709/8195143 主要jar包: 配置文件:web.xml <?xml version=" ...

  3. java数字金额转化为中文金额

    public static String digitUppercase(double n){String fraction[] = {"角", "分"};Str ...

  4. 表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的

    jQuery代码 <input value="请输入用户名" type="text"> <input value="请输入密码&qu ...

  5. LeetCode 买卖股票的最佳时机 II

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必须在再次 ...

  6. fsm三种建模思路比较

    ==================================================================================================== ...

  7. Day11名称空间,作用域,闭包函数

    Day11 1.函数对象: ①可以被引用 ​ ②可以作为另一个函数的参数 ​ ③可以作为另一个函数的返回值0 ​ ④可以被存储到容器类型中 2.函数嵌套: ①嵌套调用:在一个函数中调用了另一个函数 ​ ...

  8. Linux下制作不用密码可立即登录的SSH用户

    一.客户端建立两把钥匙 (1)本例以客户端的monkey用户为例,首先切换到~/.ssh目录下,如果没有该目录的话,需要进行新建 cd ~ mkdir .ssh chmod 700 .ssh cd ~ ...

  9. js-dom-EventUtil

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. strcat strcpy 源代码,用指针去实现

    15. 指针实现 strcmp函数     •    int newStrcpy(char *p, char *q)     •    {     •        while(*p ==*q) { ...