Arrest

问题描述 :

There are (N+1) cities on TAT island. City 0 is where police headquarter located. The economy of other cities numbered from 1 to N ruined these years because they are all controlled by mafia. The police plan to catch all the mafia gangs in these N cities all over the year, and they want to succeed in a single mission. They figure out that every city except city 0 lives a mafia gang, and these gangs have a simple urgent message network: if the gang in city i (i>1) is captured, it will send an urgent message to the gang in city i-1 and the gang in city i -1 will get the message immediately.
The mission must be carried out very carefully. Once a gang received an urgent message, the mission will be claimed failed.
You are given the map of TAT island which is an undirected graph. The node on the graph represents a city, and the weighted edge represents a road between two cities(the weight means the length). Police headquarter has sent k squads to arrest all the mafia gangs in the rest N cities. When a squad passes a city, it can choose to arrest the gang in the city or to do nothing. These squads should return to city 0 after the arrest mission.
You should ensure the mission to be successful, and then minimize the total length of these squads traveled.
输入:

There are multiple test cases.
Each test case begins with a line with three integers N, M and k, here M is the number of roads among N+1 cities. Then, there are M lines. Each of these lines contains three integers X, Y, Len, which represents a Len kilometer road between city X and city Y. Those cities including city 0 are connected.
The input is ended by “0 0 0”.
Restrictions: 1 ≤ N ≤ 100, 1 ≤ M ≤ 4000, 1 ≤ k ≤ 25, 0 ≤ Len ≤ 1000
输出:

There are multiple test cases.
Each test case begins with a line with three integers N, M and k, here M is the number of roads among N+1 cities. Then, there are M lines. Each of these lines contains three integers X, Y, Len, which represents a Len kilometer road between city X and city Y. Those cities including city 0 are connected.
The input is ended by “0 0 0”.
Restrictions: 1 ≤ N ≤ 100, 1 ≤ M ≤ 4000, 1 ≤ k ≤ 25, 0 ≤ Len ≤ 1000
样例输入:

3 4 2
0 1 3
0 2 4
1 3 2
2 3 2
0 0 0
样例输出:

14

 #include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<iomanip>
using namespace std;
typedef long long ll;
const   int oo=1e9;
const   int mm=11111111;
const   int mn=888888;
int node,src,dest,edge;
int ver[mm],flow[mm],cost[mm],nex[mm];
int head[mn],dis[mn],p[mn],q[mn],vis[mn];
/**这些变量基本与最大流相同,增加了
 cost 表示边的费用,
 p 记录可行流上节点对应的反向边
 */
void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0; i<node; i++)head[i]=-1,vis[i]=0;
    edge=0;
}
void addedge(int u,int v,int f,int c)
{
    ver[edge]=v,flow[edge]=f,cost[edge]=c,nex[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,cost[edge]=-c,nex[edge]=head[v],head[v]=edge++;
}
/**以上同最大流*/
/**spfa 求最短路,并用 p 记录最短路上的边*/
bool spfa()
{
    int i,u,v,l,r=0,tmp;
    for(i=0; i<node; ++i)dis[i]=oo;
    dis[q[r++]=src]=0;
    p[src]=p[dest]=-1;
    for(l=0; l!=r; (++l>=mn)?l=0:l)
        for(i=head[u=q[l]],vis[u]=0; i>=0; i=nex[i])
            if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
            {
                dis[v]=tmp;
                p[v]=i^1;
                if(vis[v]) continue;
                vis[q[r++]=v]=1;
                if(r>=mn)r=0;
            }
    return p[dest]>-1;
}
/**源点到汇点的一条最短路即可行流,不断的找这样的可行流*/
int SpfaFlow()
{
    int i,ret=0,delta;
    while(spfa())
    {
        for(i=p[dest],delta=oo; i>=0; i=p[ver[i]])
            if(flow[i^1]<delta)delta=flow[i^1];
        for(i=p[dest]; i>=0; i=p[ver[i]])
            flow[i]+=delta,flow[i^1]-=delta;
        ret+=delta*dis[dest];
    }
    return ret;
}
int tu[110][110];

void floyd(int n)
{
    for(int k=0; k<=n; k++)
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                tu[i][j]=min(tu[i][j],tu[i][k]+tu[k][j]);
}

int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k)&&n+m+k)
    {
        int st=2*n+1,ed=2*n+2;
        prepare(2*n+3,st,ed);
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                tu[i][j]=i==j?0:oo;
        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(c<tu[a][b])
                tu[a][b]=tu[b][a]=c;
        }
        floyd(n);
        addedge(st,0,k,0);
        addedge(0,ed,k,0);
        for(int i=1; i<=n; i++)
            addedge(0,i,1,tu[0][i]),addedge(i,i+n,1,-100000),addedge(i+n,ed,1,tu[i][0]);
        for(int i=1; i<=n; i++)
            for(int j=i+1; j<=n; j++)
                addedge(i+n,j,1,tu[i][j]);
        printf("%d\n",SpfaFlow()+100000*n);
    }
    return 0;
}

 #include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#define MIN(a , b) ((a) < (b) ? (a) : (b))
using namespace std;
const int inf = 100010;
const int maxn = 102;
const int maxe = 20000;
const int maxm = 28;
struct node
{
    int v,w,c;
    int next;
}edge[maxe << 1];
int head[maxn << 1],dis[maxn << 1],pre[maxn << 1],bj[maxn << 1];
int map[maxn][maxn];
bool vis[maxn << 1];
queue <int> Q;
int m,n,k,idx,s,ss,t;

void init()
{
    for(int i=0;i<=n;i++)
    {
        map[i][i] = 0;
        for(int j=0;j<=n;j++)
        {
            map[i][j] = map[j][i] = inf;
        }
    }
    return;
}

void read()
{
    int u,v,w;
    for(int i=0;i<m;i++)
    {
        scanf("%d %d %d",&u,&v,&w);
        if(map[u][v] > w)
        {
            map[u][v] = map[v][u] = w;
        }
    }
    return;
}

void floyd()
{
    for(int k=0;k<=n;k++)
    {
        for(int i=0;i<=n;i++)
        {
            if(i == k || map[i][k] == inf) continue;
            for(int j=0;j<=n;j++)
            {
                if(j == i || j == k || map[k][j] == inf) continue;
                if(map[i][k] + map[k][j] < map[i][j])
                {
                    map[i][j] = map[i][k] + map[k][j];
                    map[j][i] = map[i][j];
                }
            }
        }
    }
    return;
}

void addedge(int u,int v,int w,int c)
{
    edge[idx].v = v;
    edge[idx].w = w;
    edge[idx].c = c;
    edge[idx].next = head[u];
    head[u] = idx++;

    edge[idx].v = u;
    edge[idx].w = 0;
    edge[idx].c = -c;
    edge[idx].next = head[v];
    head[v] = idx++;
    return;
}

void make(int lim)
{
    memset(head,-1,sizeof(head));
    memset(bj,-1,sizeof(bj));
    s = idx = 0;
    ss = 2*n+1;
    t = 2*n+2;
    addedge(s,ss,lim,0);
    for(int i=1;i<=n;i++)
    {
        if(map[0][i] < inf)
        {
            addedge(ss,i,inf,map[0][i]);
            addedge(i+n,t,inf,map[i][0]);
        }
        addedge(i,i+n,1,-inf);
        for(int j=i+1;j<=n;j++)
        {
            if(map[i][j] < inf)
            {
                addedge(i+n,j,inf,map[i][j]);
            }
        }
    }
    return;
}

bool spfa(int st)
{
    memset(vis,false,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    while(!Q.empty())
    {
        Q.pop();
    }
    for(int i=0;i<=t;i++)
    {
        dis[i] = (i == st) ? 0 : inf;
    }
    Q.push(st);
    vis[st] = true;
    while(!Q.empty())
    {
        int cur = Q.front();
        Q.pop();
        vis[cur] = false;
        for(int i=head[cur];i != -1;i=edge[i].next)
        {
            if(edge[i].w > 0 && dis[edge[i].v] > dis[cur] + edge[i].c)
            {
                dis[edge[i].v] = dis[cur] + edge[i].c;
                pre[edge[i].v] = i;
                if(vis[edge[i].v] == false)
                {
                    vis[edge[i].v] = true;
                    Q.push(edge[i].v);
                }
            }
        }
    }
    return dis[t] < inf;
}

void solve()
{
    int res = inf;
    for(int i=1;i<=k;i++)
    {
        make(i);
        int ans = 0;
        while(spfa(s))
        {
            int dx = inf;
            int top = t;
            while(top != s)
            {
                dx = MIN(dx , edge[pre[top]].w);
                top = edge[pre[top]^1].v;
            }
            top = t;
            while(top != s)
            {
                ans += dx * edge[pre[top]].c;
                edge[pre[top]].w -= dx;
                edge[pre[top]^1].w += dx;
                top = edge[pre[top]^1].v;
            }
        }
        res = MIN(res , ans + n * inf);
    }
    printf("%d\n",res);
    return;
}

int main()
{
    while(scanf("%d %d %d",&n,&m,&k) && n+m+k)
    {
        init();
        read();
        floyd();
        solve();
    }
    return 0;
}