您的位置:首页 > 其它

hdu 4411 Arrest(最小费用最大流)

2012-10-04 19:06 393 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4411

题目大意:从0开始按1到N的顺序,遍历所有的点,并回到0点;

解题思路:费用流!

#include<iostream>

#include<string.h>

#include<stdio.h>

#include<queue>

using namespace std;

#define MAXN 205

#define MAXE 16005

#define INF 1000000

queue<int> que;

int g[MAXN][MAXN];

struct{

int node, cap, cost, next;

}edge[MAXE];

int ans, cnt, n;

int head[MAXN];

int pre[MAXN], dis[MAXN];

bool vis[MAXN];

void addEdge(int u, int node, int ca, int co){

edge[cnt].node = node;

edge[cnt].cap = ca;

edge[cnt].cost = co;

edge[cnt].next = head[u];

head[u] = cnt ++;

edge[cnt].node = u;

edge[cnt].cap = 0;

edge[cnt].cost = -co;

edge[cnt].next = head[node];

head[node] = cnt ++;

}

bool spfa(){ // 源点为0,汇点为n。

int i, u = 0;

memset(vis, 0, sizeof(vis));

while(!que.empty())que.pop();

for(i = 1; i <= n; i++)dis[i] = INF;

dis[0] = 0;

que.push(0);

vis[0] = true;

while(!que.empty()){ // 这里最好用队列,有广搜的意思,堆栈像深搜。

int u = que.front();

que.pop();

for(vis[u] = false,i = head[u]; ~i; i = edge[i].next){

int node = edge[i].node;

if(edge[i].cap && dis[node] > dis[u] + edge[i].cost){

dis[node] = dis[u] + edge[i].cost;

pre[node] = i;

if(!vis[node]){

vis[node] = true;

que.push(node);

}

}

}

}

if(dis
== INF) return false;

return true;

}

void end(){

int u, p, sum = INF;

for(u = n; u != 0; u = edge[p^1].node){

p = pre[u];

sum = min(sum, edge[p].cap);

}

//maxflow += sum;//求最大流

for(u = n; u != 0; u = edge[p^1].node){

p = pre[u];

edge[p].cap -= sum;

edge[p^1].cap += sum;

ans += sum * edge[p].cost; // cost记录的为单位流量费用,必须得乘以流量。

}

}

void floyd(int N)

{

int i, j, k;

for(k = 0; k <= N; k++)

for(i = 0; i <= N; i++)

{

for(j = 0; j <= N; j++)

{

if(g[i][j] > g[i][k] + g[k][j])

g[i][j] = g[j][i] = g[i][k] + g[k][j];

}

}

return ;

}

int main(){

int N, M, K, i, j, s, t, a, b, c;

while(scanf("%d%d%d", &N, &M, &K)&&(N + M + K))

{

for(i = 0; i <= N; i++)

{

g[i][i] = 0;

for(j = i + 1; j <= N; ++ j )

g[i][j] = g[j][i] = INF;

}

while(M--)

{

scanf("%d%d%d", &a, &b, &c);

if(g[a][b]>c)g[a][b] = g[b][a] = c;

}

floyd(N);

s = 0,t = 2 * N + 2;

cnt = 0;

memset(head, -1, sizeof(head));

for(i = 0; i <= N; i++)

{

if(i)addEdge(i, N + i + 1, 1, -INF);

else addEdge(i, N + i + 1, K, 0);

for(j = i + 1; j <= N; ++ j )

addEdge(N + i + 1, j, INF, g[i][j]);

}

for(i = 0; i <= N; i++)

addEdge(i + N + 1, t, INF, g[0][i]);

ans = 0;//ans为最小费用

//maxflow = 0;

n = t;

while(spfa())

end();

printf("%d\n", ans + N * INF);

}

return 0;

}

/*

1 1 1

0 1 1

3 4 2

0 1 3

0 2 4

1 3 2

2 3 2

0 0 0

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: