Description
分析
这题是在最短路上研究问题的,所以理所当然要建个图先。
其次我们先考虑费用,看看这图,再YY一下,那么我们可以发现这就是典型的最小割问题,可是我们还是要考虑如何判断这个割是否唯一。
首先,大家可以先去看我的另一个blog,上面有写类似这样的判断最大流是否唯一。http://blog.csdn.net/xieguofu2014/article/details/50682700
其实这两题是不同的。。。所以我在考试时就挂了。。
因为这题比较特殊,不是一般的网络流(这个自己体会一下吧。。不好说。)
但是我们知道也有一些条件是一定要满足的比如说
某些边流满的边且左右两边属于s和t集的原流量和一定是原最大流的值,即所有属于割集的边的流量和是否为原最大流,这是来预防两条连续满流的边
另一个条件是一条一定是割集的边一条边的两个节点的费用一样,那么这也是有多解的
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=405;
const int M=4005;
char cher[10],chee[10];
ll x[M],y[M],e[M*2],er[M*2],n,m,z[M],val[N],nu,b[M*2],las[N],nex[M*2],dis[N],l,r,a[M*2],v[M*2],tot[N],re[M*2],t,ty[M][3],q[N][N];
bool bz[N];
void add(int x,int y,int z,int k){
b[++nu]=y;e[nu]=x;nex[nu]=las[x];las[x]=nu;v[nu]=z;re[nu]=nu+1;er[nu]=z;
if (k) b[++nu]=x,nex[nu]=las[y],las[y]=nu,v[nu]=0,re[nu]=nu-1;
}
bool pd(){
int l=0,r=1;a[1]=1;memset(tot,0,sizeof(tot));tot[1]=1;
while (l<r){
for(int p=las[a[++l]];p;p=nex[p])
if (v[p]>0&&!tot[b[p]]) a[++r]=b[p],tot[b[p]]=tot[a[l]]+1;
}
return tot[n];
}
int ditch(int x,ll y){
if (x==n) return y;
ll we=0;
for(int p=las[x];p;p=nex[p]){
if (tot[b[p]]==tot[x]+1&&v[p]>0){
int w=ditch(b[p],min(y,v[p]));
if (w) {
y=y-w;v[p]=v[p]-w;v[re[p]]=v[re[p]]+w;
we=we+w;if (!y) break;
}
}
}
return we;
}
int bed[N];
void dfs(int x,int z){
bed[x]=z+1;
for(int p=las[x];p;p=nex[p])
if (v[p^z]&&!bed[b[p]]) dfs(b[p],z);
}
int main(){
scanf("%lld",&t);
for(;t;t--){
scanf("%lld %lld",&n,&m);nu=0;
memset(las,0,sizeof(las));
for(int i=1;i<=n-1;i++) scanf("%lld",&val[i]);
for(int i=1;i<=m;i++){
scanf("%lld %lld %lld",&x[i],&y[i],&z[i]);
add(x[i],y[i],z[i],0),add(y[i],x[i],z[i],0);
}
memset(dis,127,sizeof(dis));
memset(bz,0,sizeof(bz));
l=0;r=1;a[1]=1;bz[1]=1;dis[1]=0;
while (l<r){
for(int p=las[a[++l]];p;p=nex[p]){
if (dis[b[p]]>dis[a[l]]+v[p]) {
dis[b[p]]=dis[a[l]]+v[p];
if (!bz[b[p]])bz[b[p]]=1,a[++r]=b[p];
}
}bz[a[l]]=0;
}
memset(las,0,sizeof(las));val[n]=2000000007;
int cnt=0;nu=1;
for(int i=1;i<=m;i++){
if (dis[x[i]]==dis[y[i]]+z[i]) add(y[i],x[i],min(val[x[i]],val[y[i]]),1);
if (dis[y[i]]==dis[x[i]]+z[i]) add(x[i],y[i],min(val[x[i]],val[y[i]]),1);
}
ll ans=0;
while (pd()) ans+=ditch(1,4005000000000);
memset(bed,0,sizeof(bed));
dfs(1,0);
dfs(n,1);
ll sum=0,pew=0;
for(int i=1;i<=nu;i++)
if ((!(i&1))&&(bed[b[i]]==2&&bed[e[i]]==1)&&!v[i]) {
sum+=er[i];if (val[b[i]]==val[e[i]]) pew=1;
}
cher[0]='Y',cher[1]='e',cher[2]='s';chee[0]='N';chee[1]='o';
if (sum!=ans) {
printf("%s %d\n",chee,ans);continue;
}
if (pew) printf("%s %lld\n",chee,ans);else printf("%s %lld\n",cher,ans);
}
}