題意
從大連到上海再到西安,不能通過同一個點兩次,求最短路徑
題解
建費用流,流的費用爲長度,對城市拆點限制流量即可滿足不通過同一個點兩次。
代碼
#include <bits/stdc++.h>
#define infi 0x3f3f3f3fLL
#define kN 40010LL
#define kM 120010LL
using namespace std;
struct FST {int to,next,flow,cost;}e[kM<<1];
int star[kN], te;
void FST_init() {memset(star,0,sizeof star);te=1;}
void AddEdge(int u,int v,int cap,int cost) {
te++;
e[te].to=v;e[te].next=star[u];star[u]=te;
e[te].flow=cap,e[te].cost=cost;
te++;
e[te].to=u;e[te].next=star[v];star[v]=te;
e[te].flow=0,e[te].cost=-cost;
}
deque<int>q;
bool inq[kN];
int dis[kN],pre[kN];
int S,T,MCMF,FLOW;
bool spfa() {
int u,v,p,aug;
memset(dis,0x3f,sizeof dis);
q.push_back(S);
dis[S]=0,pre[S]=0;
while(!q.empty())
for(u=q.front(),q.pop_front(),inq[u]=false,p=star[u];p;p=e[p].next)
if(v=e[p].to,e[p].flow>0&&dis[v]>dis[u]+e[p].cost)
if(dis[v]=dis[u]+e[p].cost,pre[v]=p,!inq[v])
if(inq[v]=true,!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v);
else q.push_back(v);
if (dis[T]==infi) return false;
aug = infi;
for(p=pre[T];p;p=pre[e[p^1].to])
if (aug>e[p].flow) aug=e[p].flow;
for(p=pre[T];p;p=pre[e[p^1].to])
e[p].flow-=aug,e[p^1].flow+=aug;
MCMF += dis[T]*aug;
FLOW += aug;
return true;
}
char str[1000];
string ReadCity() {
//scanf("%s",str);
//string ret = str;
string ret;
cin>>ret;
return ret;
}
map<string,int>ID;
int idx=0;
int reg(string a) {
if (ID.find(a)!=ID.end()) return ID[a];
idx++;
ID[a] = idx;
return idx;
}
inline void work() {
int i,j,k,l,m;
ID.clear();
FST_init();
idx=0;
string DL = "Dalian";
string SH = "Shanghai";
string XA = "Xian";
reg(DL),reg(SH),reg(XA);
string a,b;
//scanf("%d",&m);
cin>>m;
for(i=1;i<=m;i++) {
a=ReadCity(),b=ReadCity();//,scanf("%d",&l);
cin>>l;
j=reg(a),k=reg(b);
AddEdge(j*2,k*2-1,1,l);
AddEdge(k*2,j*2-1,1,l);
}
j = reg(SH);
S = j*2-1;
T = idx*2+1;
for(i=1;i<=idx;i++) {
if (i == j) AddEdge(i*2-1,i*2,2,0);
else AddEdge(i*2-1,i*2,1,0);
}
j = reg(DL);
AddEdge(j*2,T,1,0);
j = reg(XA);
AddEdge(j*2,T,1,0);
MCMF=FLOW=0;
while(spfa());
if (FLOW==2) printf("%d\n",MCMF);
else puts("-1");
}
int main() {
int T;
//scanf("%d",&T);
cin>>T;
while(T-->0) work();
return 0;
}