bzoj 3258: 秘密任务

来源:互联网 发布:阿里云发票信息修改 编辑:程序博客网 时间:2024/05/24 04:34

Description

Alice听说在一片神奇的大陆MagicLand,有一个古老的传说…… 
 很久很久以前,那个时候 MagicStates共和国刚刚成立。 反对新政府的势力虽已被镇压,但仍然在暗地活动。这一次,情报局得到了一个令人震惊的消息,被软禁在首都府邸中的Frank ——著名的反对派领袖,秘密逃出首都,去往反对派的大本营。根据相关的情报,Frank计划通过城市之间 发达的高速公路,经过最短的路程抵达目的地。不妨将 MagicStates共和国简化为由N个城市,M条高速公路构成的连通的无向图,首都为城市1,反对派的大本营为城市N。 
每条高速公路连接两个不同的城市,且路程是已知的。而Frank选择了一条从城市1到城市N的最短路径作为他的逃跑路线。为了阻止Frank,共和国总统决定在某些城市的高速公路的出入口设立检查 点,在Frank经过检查点时将他逮捕。 
举例来说,如果有一条高速公路连接城市u和城市v,在这条公路的城市u或城市v的出入口设立检查点,那么Frank经过高速公路时就会被发现。特别的是,由于城市N实际上处在反对派的控制下,所以不能在城市N设立检查点。

然而在任何城市设立检查点都需要一定的费用。更具体的,若在城市 u设立k个检查点,就要花费 Au乘以k的代价,其中Au是城市u的相关参数。值得注意的是,这个代价与这k个检查点具体设在哪些公路的出入口无关,于是,总统责令情报局拟定一个方案,花费最小的代价使得无论Frank选择哪条最短路线,都会在(除城市N以外)某个城市的高速公路出入口被发现。读到这里,Alice很想知道阻止Frank所需要花费的最小代价,并且她还希 望知道最优方案是否是唯一的。只好再请你帮助她了。 
注意,我们称两个方案不同当且仅当存在某城市k,两种方案中在城市 k的检查点的设置(而不仅是数目)是不同的。 
注意,输入文件包含多组测试数据。

Input

第一行包含一个正整数T,表示有T组测试数据。接下来依次是T组测试数据。 
 每组测试数据的第一行包含两个整数 N、M。 
第二行包含N - 1个正整数,依次表示A1,A2, …,An-1。
接下来M行,每行三个整数Ui,Vi,Ci,表示一条连接城市Ui和城市Vi的路程等于Ci的高速公路

Output

输出T行,依次表示每组测试数据的答案。若最优方案唯一则输出 ”Yes” 和
最小代价,否则输出”No”和最小代价。字符串和整数之间请用一个空格隔开。

Sample Input

3
3 3
2 4
1 3 23
3 2 12
2 1 11
4 4
3 2 2
1 2 1
2 3 1
3 4 1
4 1 1
3 4
3 2
1 2 1
2 3 2
2 3 19
3 1 4

Sample Output


Yes 4
Yes 3
No 2

HINT

第1组测试数据:最优方案是在城市1 设立两个检查点。 
第2组测试数据:最优方案是城市1的高速公路( 1, 4)的出入口设立检查点。  
第3组测试数据:最优方案是在城市2设立一个检查点,不过既可以设置在
高速公路(1, 2)的出入口,也可以设置在高速公路(2, 3)的出入口。 

对于100%的数据:2 ≤ N ≤ 400 , 1≤ M  ≤ 4 000 ,1 ≤ T ≤ 5 , 
1 ≤ Ai, c ≤ 10^9。无向图可能有重边。 


最短路图+求最小割+判断最小割是否唯一

最短路图可以用spfa求。然后最小割

然后判断最小割是否唯一的时候。网上有个bfs的方法=-=不过我偷了个懒所以贴了个tarjan模板上去

tarjan缩点之后。判断是否所有不在一个联通块的满流边都是S所在联通块指向T所在。是的话唯一。不是的话不唯一

= =Yes和No写成了YES和NO

记得spfa的dis要开longlong

记得如果最小割中的边两个端点权值相同则不为已

都是坑!


#include<queue>#include<cstdio>#include<string>#include<cstring>using namespace std;inline int min(int x,int y){     if(x<y)          return x;     return y;}int head[100001],exhead[100001];struct map{ long long f; int s,t;     int next;}a[400001],exa[400001];int edge,exedge;int p;int q[400001],d[400001];int haedge[400001];inline void add1(int s,int t,int f,int xxx){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;     a[edge].f=f;     haedge[xxx]=edge;}inline void add(int s,int t,long long f){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;     a[edge].f=f;}inline void exadd(int s,int t,long long f){     exa[exedge].next=exhead[s];     exhead[s]=exedge;     exa[exedge].s=s;     exa[exedge].t=t;     exa[exedge].f=f;}inline bool bfs(){     int l=0,r=0;     memset(q,0,sizeof(q));     r++;     q[r]=1;     memset(d,-1,sizeof(d));     d[1]=0;     int i,k;     while(l<r)     {       l++;          int k=q[l];          for(i=head[k];i!=0;i=a[i].next)          {               if(a[i].f>0&&d[a[i].t]==-1)               {                    d[a[i].t]=d[k]+1;                    r++;                    q[r]=a[i].t;               }          }     }     if(d[p]>=0)          return true;     return false;}inline int dfs(int k,int s){     if(k==p)          return s;     int t=s;     int i;     for(i=head[k];i!=0;i=a[i].next)     {          if(d[a[i].t]==d[k]+1&&a[i].f>0)          {               int xx=dfs(a[i].t,min(s,a[i].f));               a[i].f-=xx;               if(i%2==0)                    a[i-1].f+=xx;               else                    a[i+1].f+=xx;               s-=xx;          }     }     return t-s;}inline int maxflow(){     int s=0;     while(bfs())          s+=dfs(1,2100000000);     return s;}long long dis[401];bool v[401];inline void spfa(){ int i; for(i=1;i<=400;i++)      dis[i]=(long long)1000000000*(long long)4000; memset(v,false,sizeof(v));     queue <int>Q;     while(!Q.empty())          Q.pop();     Q.push(1);     dis[1]=0;     v[1]=true;     while(!Q.empty())     {          int d=Q.front();          v[d]=false;          Q.pop();          int i;          for(i=exhead[d];i!=0;i=exa[i].next)          {               int t=exa[i].t;               if(dis[d]+exa[i].f<dis[t])               {                    dis[t]=dis[d]+exa[i].f;                    if(!v[t])                    {                         Q.push(t);                         v[t]=true;                    }               }          }     }}int scc,cnt;int s[10001],top;int dfn[10001],low[10001],belong[10001];inline void tarjan(int d){     int i,x;     cnt++;     dfn[d]=cnt;     low[d]=cnt;     top++;     s[top]=d;     v[d]=true;     for(i=head[d];i!=0;i=a[i].next)     {       if(a[i].f==0)            continue;       x=a[i].t;          if(dfn[x]==0)          {               tarjan(x);               low[d]=min(low[d],low[x]);          }          else if(v[x]&&low[d]>dfn[x])//v在栈中,修改low[u]               low[d]=dfn[x];     }     if(dfn[d]==low[d])//u为该强连通分量中遍历所成树的根     {          scc++;          x=s[top];          top--;          while(x!=d)          {       v[x]=false;               belong[x]=scc;               x=s[top];               top--;          }          v[x]=false;          belong[x]=scc;     }}int dk[4001];struct cc{     int ss,tt,x;}ed[1000001];int main(){     int T;     scanf("%d",&T);     while(T>0)     {          T--;          memset(head,0,sizeof(head));          memset(a,0,sizeof(a));          memset(exhead,0,sizeof(exhead));          memset(exa,0,sizeof(exa));  memset(haedge,0,sizeof(haedge));          edge=0;          exedge=0;  int n,m;          scanf("%d%d",&n,&m);          int i;          for(i=1;i<=n-1;i++)               scanf("%d",&dk[i]);          dk[n]=2100000000;           int s,t,x;          for(i=1;i<=m;i++)          {               scanf("%d%d%d",&s,&t,&x);               exedge++;               exadd(s,t,x);               exedge++;               exadd(t,s,x);          }          spfa();          int pp=0;          for(i=1;i<=exedge;i++)          {               if(dis[exa[i].s]+exa[i].f==dis[exa[i].t])               {                    x=dk[exa[i].s];                    x=min(x,dk[exa[i].t]);pp++;                    ed[pp].ss=exa[i].s;ed[pp].tt=exa[i].t;ed[pp].x=x;                    edge++;                    add1(ed[pp].ss,ed[pp].tt,ed[pp].x,pp);                    edge++;                    add(ed[pp].tt,ed[pp].ss,0);               }          }          p=n;          int ans=maxflow();          memset(v,false,sizeof(v));          memset(dfn,0,sizeof(dfn));          memset(low,0,sizeof(low));          memset(belong,0,sizeof(belong));          top=0;          for(i=1;i<=n;i++)               if(dfn[i]==0)                    tarjan(i);          int flag=-1;          for(i=1;i<=pp;i++)          {               if(a[haedge[i]].f==0)               {                    if(belong[ed[i].ss]==belong[1]&&belong[ed[i].tt]!=belong[n]&&belong[ed[i].tt]!=belong[1]||dk[ed[i].ss]==dk[ed[i].tt])                    {                         flag=0;                         break;                    }               }          }          if(flag==-1)               printf("Yes ");          else               printf("No ");          printf("%d\n",ans);     }     return 0;}



0 0
原创粉丝点击