题解转自:https://www.cnblogs.com/Chen-Jr/p/11228767.html
题目链接:https://vjudge.net/problem/HDU-6582
题意:给你一张有向图,现在你需要删除一些边,每次删除的花费是边的权值,使得最短路增大,现在问你最小的花费。
思路:让最短路变长,应该先把最短路拿出来建图然后用一个最小的花费破坏这个图即可。首先以1号节点跑dijkstra,然后以n号节点跑dijkstra。遍历每一条边,如果dist[xx[i]]+c[i]+dist1[yy[i]]==dist[n],说明这条边就是最短路上的一条边,然后用dinic跑最大流即可。
#pragma comment(linker,"/STACK":102400000,102400000")
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <utility>
using namespace std;
const int maxn=1e4+5;
long long dist[maxn],dist1[maxn];
const long long inf=1e16;
const int inf1=1e9+5;
vector <pair<int,int> >g[maxn];
bool done[maxn];
int xx[maxn],yy[maxn],c[maxn];
struct heapnode
{
long long d;
int u;
bool operator <(const heapnode &s) const
{
return d>s.d;
}
};
int n,m;
priority_queue <heapnode> q;
void dijkstra(int s,long long *d)
{
memset(done,0,sizeof(done));
for(int i=1;i<=n;i++)
{
d[i]=inf;
}
q.push(heapnode{0,s});
d[s]=0;
while(!q.empty())
{
heapnode x=q.top();
q.pop();
int u=x.u;
if(done[u])
continue;
done[u]=true;
for(int i=0;i<g[u].size();i++)
{
int to=g[u][i].first;
int w=g[u][i].second;
if(d[to]>d[u]+w)
{
d[to]=d[u]+w;
q.push(heapnode{d[to],to});
}
}
}
return ;
}
struct edge
{
int to,cap,rec;
};
vector <edge> gg[maxn];
int level[maxn];
int iter[maxn];
void add(int from,int to,int cap)
{
gg[from].push_back((edge){to,cap,gg[to].size()});
gg[to].push_back((edge){from,0,gg[from].size()-1});
}
void bfs(int s)
{
memset(level,-1,sizeof(level));
queue<int> q;
q.push(s);
level[s]=1;
while(!q.empty())
{
int v=q.front();
q.pop();
for(int i=0;i<gg[v].size();i++)
{
edge &e=gg[v][i];
if(e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
q.push(e.to);
}
}
}
}
int dfs(int v,int t,int f)
{
if(v==t)
{
return f;
}
for(int &i=iter[v];i<gg[v].size();i++)
{
edge &e=gg[v][i];
if(e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(e.cap,f));
if(d>0)
{
e.cap-=d;
gg[e.to][e.rec].cap+=d;
return d;
}
}
}
return 0;
}
int maxflow(int s,int t)
{
int flow=0;
while(1)
{
bfs(s);
if(level[t]<0)
{
return flow;}
memset(iter,0,sizeof(iter));
int f;
while((f=dfs(s,t,inf1))>0)
{
flow+=f;
}
}
}
int main()
{int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&xx[i],&yy[i],&c[i]);
g[xx[i]].push_back(make_pair(yy[i],c[i]));
}
dijkstra(1,dist);
for(int i=1;i<=n;i++)
{
g[i].clear();
}
for(int i=0;i<m;i++)
{
g[yy[i]].push_back(make_pair(xx[i],c[i]));
}
dijkstra(n,dist1);
for(int i=0;i<m;i++)
{
if(dist[xx[i]]+c[i]+dist1[yy[i]]==dist[n])
{
add(xx[i],yy[i],c[i]);
}
}
printf("%d\n",maxflow(1,n));
for(int i=1;i<=n;i++)
{
g[i].clear();
gg[i].clear();
}
}
return 0;
}