Description
给出一张nn个点条边的无向图,边权均为11,敌人在点准备走最短路在攻击己方位置11点,现在要在一些边上设置一些路障,给出每条边设置路障的代价,要求用最少的代价设置路障使得敌人必然遇到路障
Input
第一行一整数表示用例组数,每组用例首先输入两个整数n,mn,m表示点数和边数,之后mm行每行输入三个整数表示u,vu,v之间有一条边且在该条边上设置路障代价为ww
Output
输出使得敌人必然遇到路障的最小代价
Sample Input
1
4 4
1 2 1
2 4 2
3 1 3
4 3 4
Sample Output
4
Solution
以11为起点整张图找出最短路,所有在最短路上的边均可能被敌人走,以这些最短路上的边建新图,问题即转化为求新图的最小割
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
#define maxn 1111
#define maxm 22222
#define INF 0x3f3f3f3f
int head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no;//s为源点,e为汇点,n为点数,no为边数
struct point
{
int u,v,flow,next;
point(){};
point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};
}p[maxm];
void add(int x,int y,int z)//从x到y建容量为z的边
{
p[no]=point(x,y,head[x],z);//前向弧,标号为偶
head[x]=no++;
p[no]=point(y,x,head[y],0);//后向弧,标号为奇
head[y]=no++;
}
void init()//初始化
{
memset(head,-1,sizeof(head));
no=0;
}
bool bfs()
{
int i,x,y;
queue<int>q;
memset(d,-1,sizeof(d));
d[s]=0;
q.push(s);
while(!q.empty())
{
x=q.front();
q.pop();
for(i=head[x];i!=-1;i=p[i].next)
{
if(p[i].flow&& d[y=p[i].v]<0)
{
d[y]=d[x]+1;
if(y==e)
return true;
q.push(y);
}
}
}
return false;
}
int dinic()//最大流
{
int i,loc,top,x=s,nowflow,maxflow=0;
while(bfs())
{
memcpy(cur,head,sizeof(head));
top=0;
while(true)
{
if(x==e)
{
nowflow=INF;
for(i=0;i<top;i++)
{
if(nowflow>p[st[i]].flow)
{
nowflow=p[st[i]].flow;
loc=i;
}
}
for(i=0;i<top;i++)
{
p[st[i]].flow-=nowflow;
p[st[i]^1].flow+=nowflow;
}
maxflow+=nowflow;
top=loc;
x=p[st[top]].u;
}
for(i=cur[x];i!=-1;i=p[i].next)
if(p[i].flow&&d[p[i].v]==d[x]+1)
break;
cur[x]=i;
if(i!=-1)
{
st[top++]=i;
x=p[i].v;
}
else
{
if(!top)
break;
d[x]=-1;
x=p[st[--top]].u;
}
}
}
return maxflow;
}
typedef pair<int,int> P;
vector<P>g[maxn];
int T,n,m,dis[maxn],vis[maxn];
void add_edge(int u,int v,int w)
{
g[u].push_back(P(v,w)),g[v].push_back(P(u,w));
}
void BFS(int s)
{
queue<int>que;
while(!que.empty())que.pop();
for(int i=1;i<=n;i++)vis[i]=0,dis[i]=INF;
que.push(s),dis[s]=0,vis[s]=1;
while(!que.empty())
{
int u=que.front();
if(u==n)return ;
que.pop();
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].first;
if(vis[v])continue;
dis[v]=dis[u]+1,vis[v]=1,que.push(v);
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)g[i].clear();
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
BFS(1);
//for(int i=1;i<=n;i++)printf("dis[%d]=%d\n",i,dis[i]);
init();
s=1,e=n;
for(int u=1;u<=n;u++)
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].first,w=g[u][i].second;
if(dis[v]==dis[u]+1)add(u,v,w);
}
printf("%d\n",dinic());
}
}