思路:无向图,加边时需要两个方向,然后加一个超级源点0,0到1的容量为D,然后求最小费用最大流,如果=D,则输出最小费用,否则Impossible.注意数据的范围,要用long long。
附代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;
const LL INF=10000000000000000;
const int maxn=110;
const int maxm=5050;
struct node
{
int u,v,next,cap;
LL cost;
}edge[maxm*4];
int vis[maxn],pre[maxn],head[maxn];
LL dis[maxn];
int N,M,num;
LL D,K;
void add_edge(int x,int y,LL f)
{
edge[num].u=x;
edge[num].v=y;
edge[num].cost=f;
edge[num].next=head[x];
head[x]=num++;
edge[num].u=y;
edge[num].v=x;
edge[num].cost=-f;
edge[num].next=head[y];
head[y]=num++;
}
bool spfa(int s,int t)
{
int cur;
for(int i=0;i<=N;i++)
{
dis[i]=INF;
vis[i]=0;
pre[i]=-1;
}
queue<int> q;
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty())
{
cur=q.front();
q.pop();
vis[cur]=0;
for(int i=head[cur];i!=-1;i=edge[i].next)
{
if(edge[i].cap)
{
int v=edge[i].v;
if(dis[v]>dis[cur]+edge[i].cost)
{
dis[v]=dis[cur]+edge[i].cost;
pre[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
return dis[t]!=INF;
}
LL mincost(int s,int t)
{
LL flow=INF,ans1=0,ans=0;
while(spfa(s,t))
{
for(int i=pre[t];i!=-1;i=pre[edge[i].u])
flow=flow>edge[i].cap?edge[i].cap:flow;
ans1+=flow;
ans+=flow*dis[t];
for(int i=pre[t];i!=-1;i=pre[edge[i].u])
{
edge[i].cap-=flow;
edge[i^1].cap+=flow;
}
}
return ans1==D?ans:-1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int x,y;
LL f;
while(scanf("%d%d",&N,&M)!=EOF)
{
num=0;
memset(head,-1,sizeof(head));
for(int i=0;i<M;i++)
{
scanf("%d%d%lld",&x,&y,&f);
add_edge(x,y,f);
add_edge(y,x,f);
}
scanf("%lld%lld",&D,&K);
add_edge(0,1,0);
edge[num-2].cap=D;
edge[num-1].cap=0;
for(int i=0;i<num-2;i++)
{
if(edge[i].cost<0)edge[i].cap=0;
else edge[i].cap=K;
}
LL ans=mincost(0,N);
if(ans==-1)cout<<"Impossible."<<endl;
else cout<<ans<<endl;
}
return 0;
}