题意:从1走到n,然后从n再回到1,不走重复的边,所走的最短路。(不一定每个点都要走);
输入 a,b,c,c即为费用。设a,b边的流量为1. 用0作为源点,n+1作为汇点,0,1连的边流量为2,费用为0,n,n+1连的边流量为2,费用为0;建图。
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 0x7fffffff
#define maxn 50050
struct ss
{
int u,v,w,f;
int next;
}edge[maxn];
int pre[maxn/2],vis[maxn/2],dis[maxn/2],head[maxn/2];
int s,t,n,top,m;
int mincost;
void add(int u,int v,int w,int f)
{
edge[top].v=v;
edge[top].u=u;
edge[top].f=f;
edge[top].w=w;
edge[top].next=head[u];
head[u]=top++;
}
bool spfa()
{
int i,j;
for(i=0;i<=n+2;i++) dis[i]=inf;
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
dis[s]=0;
vis[s]=1;
pre[s]=-1;
while(!q.empty())
{
int u=q.front(); q.pop();
vis[u]=0;
for(j=head[u];j!=-1;j=edge[j].next)
{
if(edge[j].f>0&&dis[u]+edge[j].w<dis[edge[j].v])
{
dis[edge[j].v]=dis[u]+edge[j].w;
pre[edge[j].v]=j;
if(!vis[edge[j].v])
{
vis[edge[j].v]=1;
q.push(edge[j].v);
}
}
}
}
if(dis[t]<inf) return true;
else return false;
}
int fun()
{
int i;
int minflow=inf;
for(i=pre[t];i!=-1;i=pre[edge[i].u])
if(minflow>edge[i].f)
minflow=edge[i].f;
for(i=pre[t];i!=-1;i=pre[edge[i].u])
{
edge[i].f-=minflow;
edge[i^1].f+=minflow;
mincost+=edge[i].w*minflow;
}
return 0;
}
void init(int u,int v,int w,int c)
{
add(u,v,w,c);
add(v,u,-w,0);
}
int main()
{
//freopen("Input.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
top=0;
mincost=0;
int a,b,c;
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
init(a,b,c,1);
init(b,a,c,1);
}
s=0;t=n+1;
init(s,1,0,2);
init(n,t,0,2);
while(spfa())
fun();
printf("%d\n",mincost);
}
return 0;
}