War

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1545    Accepted Submission(s): 338


Problem Description
In the war between Anihc and Bandzi, Anihc has won Bangzi. At that time, Lvbin, the king of Anihc, want to start from Bangzi to beat Nebir across the channel between them. He let his army get to there as soon as possible, and there located many islands which can be used to have a break. In order to save time, the king forbid the army getting through the same pass for more than one time, but they can reach the same island for as many as times they want.
Yunfeng, the General of the army, must tell how many optimal ship routes are there to the king as soon as possible, or he will be killed. Now he asks for your help. You must help Yunfeng to save his life.
He tells you that there are N island. The islands are numbered from 1 to N(1 is Bangzi and N is Nebir, others are many islands). And there are many ways, each way contain the islands number U and V and the length W. Please output your answer.
 

 

Input
The first line in the input file contains a single integer number T means the case number. 
Each case contains a number N (N<=1500) means the number of the islands. 
And then many lines follow. Each line contains three numbers: U V W (W<10000), means that the distance between island U and V is W. The input of ways are terminated by “ 0 0 0 ”.
 

 

Output
Print the number of the optimal ship routes are there after each case in a line.
 

 

Sample Input
1 6 1 2 1 3 2 1 3 4 1 1 3 2 4 2 2 4 5 1 5 6 1 4 6 2 0 0 0
 

 

Sample Output
2
 

网上百度这道题的题解,用的好像都是最大流的方法,不知道效率怎么样,反正我觉得是很麻烦的,我用的这个算法是我自己想的,就是一直重复spfa求最小流的过程,当发现下一个最小流比上一个最小流大的时候,就结束算法,感觉这种算法的效率还是不错的,特意贴出来分享一下。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<climits>
#define MAXN 1500*1500
using namespace std;
struct Edge
{
    int s,t,f,c,next;
} edge[MAXN];
int head[1510];
int pre[1510];
int dist[1510];
bool isq[1510];
int n,s,t,u,v,w,ent;
void add(int S,int T,int f,int c)
{
    edge[ent].s=S;
    edge[ent].t=T;
    edge[ent].f=f;
    edge[ent].c=c;
    edge[ent].next=head[S];
    head[S]=ent++;
    edge[ent].s=T;
    edge[ent].t=S;
    edge[ent].f=0;
    edge[ent].c=-c;
    edge[ent].next=head[T];
    head[T]=ent++;
}
int MIN(int a,int b)
{
    return a<b?a:b;
}
void init()
{
    ent=0;
    memset(head,-1,sizeof(head));
    while(scanf("%d%d%d",&u,&v,&w),u+v+w)
    {
        add(u,v,1,w);
        add(v,u,1,w);
    }
}
bool spfa()
{
    memset(pre,-1,sizeof(pre));//初始化路径为-1
    for(int i=s; i<=t; i++)
    {
        isq[i]=false;//每点开始时均不在队列里面
        dist[i]=INT_MAX;//初始化到每点的最小费用均为INT_MAX
    }
    queue<int>q;
    q.push(s);
    isq[s]=true;//源点s已经放入到队列里面去了
    dist[s]=0;//从源点到源点的距离为0
    while(!q.empty())//当队列为空时优化过程结束,退出循环
    {
        int temp1=q.front();
        q.pop();
        isq[temp1]=false;//该点已经退出队列
        for(int i=head[temp1]; i!=-1; i=edge[i].next) //从该点找通过邻接表找所有的以该点为起点的边,从中找出能优化的点
        {
            int temp2=edge[i].t;
            if(edge[i].f&&dist[temp2]>dist[temp1]+edge[i].c)
            {
                dist[temp2]=dist[temp1]+edge[i].c;
                pre[temp2]=i;
                if(!isq[temp2])//如果该点不在队列中,则将该点放入队列中
                {
                    q.push(temp2);
                    isq[temp2]=true;
                }
            }
        }
    }
    return pre[t]!=-1;//如果pre[t]==-1的话说明没有找到从s到t的路径,即已经找到所有的路径了,结束循环
}
void mcmf()
{
    int tot=0;
    int mincost=INT_MAX;
    int minn=INT_MAX;
    while(spfa())
    {
        if(dist[t]<=mincost)
        {
            tot++;
            mincost=dist[t];
        }
        else break;//当新求出来的最小费用大于初始的那个的时候结束算法
        for(int i=pre[t];i!=-1;i=pre[i])//最小费用最大流中的减流的过程
        {
            edge[i].f--;
            edge[i^1].f++;
            i=edge[i].s;
        }
    }
    printf("%d\n",tot);
}
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);
        s=1;t=n;
        init();
        mcmf();
    }
}