HDU 4411 Arrest

来源:互联网 发布:初学java看什么书好 编辑:程序博客网 时间:2024/05/01 07:24
#include "cstdio"#include "cstring"const int N = 333;//点const int M = 33333;//边const int inf = 10000000;int min(int a,int b){return a<b ? a:b;}struct Node{//边,点f到点t,流量为c,费用为wint f, t, c, w;}e[M];int next1[M], point[N], dis[N], q[N], pre[N], ne;//ne为已添加的边数,next,point为邻接表,dis为花费,pre为父亲节点bool u[N];void init(){memset(point, -1, sizeof(point));ne = 0;}void add_edge(int f, int t, int d1, int d2, int w){//f到t的一条边,流量为d1,反向流量d2,花费w,反向边花费-w(可以反悔)e[ne].f = f, e[ne].t = t, e[ne].c = d1, e[ne].w = w;next1[ne] = point[f], point[f] = ne++;e[ne].f = t, e[ne].t = f, e[ne].c = d2, e[ne].w = -w;next1[ne] = point[t], point[t] = ne++;}bool spfa(int s, int t, int n){int i, tmp, l, r;memset(pre, -1, sizeof(pre));for(i = 0; i < n; ++i)dis[i] = inf;dis[s] = 0;q[0] = s;l = 0, r = 1;u[s] = true;while(l != r) {tmp = q[l];l = (l + 1) % (n + 1);u[tmp] = false;for(i = point[tmp]; i != -1; i = next1[i]) {if(e[i].c && dis[e[i].t] > dis[tmp] + e[i].w) {dis[e[i].t] = dis[tmp] + e[i].w;pre[e[i].t] = i;if(!u[e[i].t]) {u[e[i].t] = true;q[r] = e[i].t;r = (r + 1) % (n + 1);}}}}if(pre[t] == -1)return false;return true;}void MCMF(int s, int t, int n, int &flow, int &cost){//起点s,终点t,点数n,最大流flow,最小花费costint tmp, arg;flow = cost = 0;while(spfa(s, t, n)) {arg = inf, tmp = t;while(tmp != s) {arg = min(arg, e[pre[tmp]].c);tmp = e[pre[tmp]].f;}tmp = t;while(tmp != s) {e[pre[tmp]].c -= arg;e[pre[tmp] ^ 1].c += arg;tmp = e[pre[tmp]].f;}flow += arg;cost += arg * dis[t];}    }int n,m,k;int d[111][111];void floyd(){    for(int k=0;k<n+1;k++)        for(int i=0;i<n+1;i++)            for(int j=0;j<n+1;j++)  d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}void input(){    for(int i=0;i<n+1;i++){        for(int j=0;j<n+1;j++){            if(i==j)  d[i][j]=0;            else  d[i][j]=inf;        }    }    int s,e,c;    for(int i=0;i<m;i++){        scanf("%d%d%d",&s,&e,&c);        d[s][e]=min(d[s][e],c);        d[e][s]=min(d[e][s],c);    }}void solve(){    floyd();    init();    int low=-1000000;    add_edge(2*n+1,0,k,0,0);    add_edge(0,2*n+2,k,0,0);    for(int i=1;i<=n;i++){        add_edge(0,i,1,0,d[0][i]);        add_edge(i,n+i,1,0,low);        add_edge(n+i,2*n+2,1,0,d[0][i]);    }    for(int i=1;i<=n;i++)        for(int j=i+1;j<=n;j++)            add_edge(n+i,j,1,0,d[i][j]);    int flow,cost;    MCMF(2*n+1,2*n+2,2*n+3,flow,cost);    printf("%d\n",cost-low*n);}int main(){    while(scanf("%d%d%d",&n,&m,&k)!=EOF){        if(n==0&&m==0&&k==0)  break;        input();        solve();    }    return 0;}

0 0
原创粉丝点击