(和poj2135很像很像,就多了一个情况而已,基础入门题)
题目大概意思为总共有N个仓库,求两条不同路径从起点到达终点,若是没有两条,打出Not possible,若是有可能打出所需最小费用
很简单把每个边容量设为1,费用则为题目所给,然后把起点和终点之间连一个很大很大的值,若是不足两条,费用就会变得很大很大,很容易判断出来,然后套最小费用流模板即可
(按题目所说的话,不仅边不能相同,点也不能相同,但可能样例比较松,不考虑点不重复也能过,如果想严谨的话,可以把一个点分为两个点来看,之间连一条容量为1,费用为0的边即可)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define INF 1000000005
using namespace std;
struct edge
{
int to, cap, coust, rev;
edge(int t, int c, int s, int r)
{
to = t; cap = c; coust = s; rev = r;
}
};
vector<struct edge> data[105];
int dist[105];
int N, M;
void add_edg(int i, int j, int k)
{
data[i].push_back(edge(j, 1, k, data[j].size()));
data[j].push_back(edge(i, 0, -k, data[i].size() - 1));
}
int min_coust(int from, int to, int flow)
{
int money = 0;
int prev[105];
int prep[105];
while(flow--)
{
fill(dist, dist + N, INF);
dist[0] = 0;
bool flag = true;
while(flag)
{
flag = false;
for(int i = 0; i < N; i++)
{
if(dist[i] != INF)
{
for(int j = 0; j < data[i].size(); j++)
{
struct edge e = data[i][j];
if(e.cap != 0 && dist[i] + e.coust < dist[e.to])
{
flag = true;
dist[e.to] = dist[i] + e.coust;
prev[e.to] = i;
prep[e.to] = j;
}
}
}
}
}
for(int i = to; i != from; i = prev[i])
{
data[prev[i]][prep[i]].cap--;
data[i][data[prev[i]][prep[i]].rev].cap++;
}
money = money + dist[to];
}
return money;
}
int main()
{
int f = 1;
while(1)
{
int a, b, c;
scanf("%d %d", &N, &M);
if(N == 0 && M == 0)
{
break;
}
for(int i = 0; i < N; i++)
{
data[i].clear();
}
for(int i = 0; i < M; i++)
{
scanf("%d %d %d", &a, &b, &c);
add_edg(a, b, c);
}
data[0].push_back(edge(N - 1, INF, INF, data[N - 1].size()));
data[N-1].push_back(edge(0, 0, -INF, data[0].size() - 1));
int d = min_coust(0, N - 1, 2);
if(d >= INF)
{
printf("Instance #%d: Not possible\n", f);
}
else
{
printf("Instance #%d: %d\n", f, d);
}
f++;
}
}