【题目】
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1646 Accepted Submission(s): 447
Problem Description
Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her.
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 and go along the shortest path to hers, indexed n.
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl's home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer.
Note, if Jerry can't reach his girl's house in the very beginning, the answer is obviously zero. And you don't need to guarantee that there still exists a way from Jerry's house to his girl's after blocking some edges.
Input
The input begins with a line containing one integer T(1≤T≤10), the number of test cases.
Each test case starts with a line containing two numbers n,m(1≤n,m≤10000), the number of houses and the number of one-way roads in the neighbourhood.
m lines follow, each of which consists of three integers x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed x to y of length c.
Output
Print T lines, each line containing a integer, the answer.
Sample Input
1 3 4 1 2 1 2 3 1 1 3 2 1 3 3
Sample Output
3
【题意】
给你一张图,去掉最少的边权使得最短路变长。
【题解】
跑两遍最短路,然后把最短路树构造出来。题意成功转化为,去掉最少的边权使得这个最短路树不连通。
那么这就是最小割的求法了。
由于最近补题时间太紧了,这个题我就没有自己打代码了。
代码来自小姐姐的博客:javascript:void(0)
【代码】
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define P pair<ll, int>
const int maxn=1e4+50;
const ll inf=0x3f3f3f3f3f3f3f3f;
struct node{
int u,v,nxt;
ll f;
}e[maxn*10];
int n,m,cnt=0;
int head[maxn];
int st,ed,ex;
vector <P> g1[maxn],g2[maxn];
ll dis1[maxn],disn[maxn];
priority_queue < P,vector<P>,greater<P> > Q;///高级骚操作
int dep[maxn];
int q[maxn*2];
int tot,tail;
void add(int u,int v,ll f)
{
e[cnt].u=u;
e[cnt].v=v;
e[cnt].f=f;
e[cnt].nxt=head[u];
head[u]=cnt++;
e[cnt].u=v;
e[cnt].v=u;
e[cnt].f=0;
e[cnt].nxt=head[v];
head[v]=cnt++;
}
void dij1(int S, ll *dis)
{
for(int i=0;i<=n;i++) dis[i]=inf;
dis[S]=0;
while(Q.size()) Q.pop();
Q.push(P(dis[S],S));
while(Q.size()){
P temp=Q.top(); Q.pop();
int u=temp.second;
if(dis[u]<temp.first) continue;
for(int i=0;i<g1[u].size();i++){
int v=g1[u][i].second;
ll w=g1[u][i].first;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
Q.push(P(dis[v],v));
}
}
}
}
void dij2(int S, ll *dis)
{
for(int i=0;i<=n;++i)
dis[i]=inf;
dis[S]=0;
while(Q.size()) Q.pop();
Q.push(P(dis[S],S));
while(Q.size()){
P temp=Q.top(); Q.pop();
int u=temp.second;
if(dis[u]<temp.first) continue;
for(int i=0;i<g2[u].size();++i){
int v=g2[u][i].second;
ll w=g2[u][i].first;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
Q.push(P(dis[v],v));
}
}
}
}
bool bfs()
{
memset(dep,-1,sizeof(dep));
dep[st]=1;
q[tot=0]=st,tail=1;
while(tot<tail){
int u=q[tot++];
if(u==ed) break;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(dep[v]!=-1||e[i].f==0) continue;
dep[v]=dep[u]+1;
q[tail++]=v;
}
}
return dep[ed]!=-1;
}
ll dfs(int u,ll flow)
{
ll res=flow;
if(u==ed) return flow;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(dep[v]!=dep[u]+1||!e[i].f) continue;
ll d=dfs(v,min(res,e[i].f));
e[i].f-=d;///步骤4增广路中所有减去d,
e[i^1].f+=d;///反向边加上d
res-=d;
if(res==0) break;
}
if(flow==res) dep[u]=-1;///这句话可能是流不下去了
return flow-res;///真正有用的流
}
ll dinic()
{
ll ans=0;
ll d;
while(bfs()){///第二步构造残留图
while(d=dfs(st,inf))///第三步找到一条增广路,
ans+=d;///只需要一次dfs过程实现多次增广路
}
return ans;
}
int main()
{
int t; scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
g1[i].clear(),g2[i].clear();
while(m--){
int u,v; ll w;
scanf("%d%d%lld",&u,&v,&w);
g1[u].push_back(P(w,v));
g2[v].push_back(P(w,u));
}
dij1(1,dis1);
dij2(n,disn);
if(dis1[n]==inf){
puts("0");
continue;
}
for(int u=1;u<=n;u++){
for(int i=0;i<g1[u].size();i++){
int v=g1[u][i].second;
ll w=g1[u][i].first;
if(dis1[u]+disn[v]+w==dis1[n])
add(u,v,w);
}
}
st=1,ed=n,ex=n+1;
printf("%lld\n",dinic());
}
return 0;
}