Path
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2034 Accepted Submission(s): 555
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
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6582
题意:
给你一个有n个点,m条边的有向图。让你以最小的代价删除一些边使得从点1到点n的最短路变长,删掉一条边的代价为这条边的长度,不连通也算长度增加,也不用考虑删完之后点1是否能到达点n。
题解:
首先由于从1到n的最短路可能存在多条,所以需要先把所有最短路上的边拎出来建一张图G;
然后在图G上跑最小割,用最小的花费把源点1和汇点n割开,割开之后原图中所有原有最短路必然不联通,此时1~n的最短路长度必然增加;
因为“最小割=最大流”定理,所以只需要在图G上跑最大流算法即可。
如何建立图G呢?
这相当于要找出从1到n的所有最短路。
如果在dijkstra中用vector记录每个节点的多个前驱节点(或边),有可能会MLE;
怎么办呢?
观察每一条边,如果其存在于从1到n的最短路上,那么满足式子:
dist[u]+cost[i]+dist2[v]==dist[n],
其中dist[j]是从1到j的最短路,cost[i]是第i条边的权值,dist2[j]是从j到n的最短路;
dist2是通过反向建图跑dijkstra得到的。
为了防止TLE,这里使用Heap+Dijkstra。
Dinic由于采用分层图、多路增广等策略,时间复杂度比其他网络流算法较优,其时间复杂度是O(n^2*m);
算起来仍然TLE,但网络流算法时间复杂度很奇怪,Dinic跑的很快,加上当前弧优化之后交就是了!
代码:
#include <bits/stdc++.h>
#define Pii pair<int,int>
using namespace std;
typedef long long llong;
const llong inf=1e16;
const int tmax=1e4+5,inf_int=1e9+5;
struct node {
llong d;
int x;
bool operator<(const node &b)const
{
return d>b.d;
}
};
int n,m,xx[tmax],yy[tmax],cc[tmax];
vector<Pii> GG[tmax];
priority_queue<node> Q;
bool vis[tmax];
llong dis[tmax],_dis[tmax];
void dijk(int s,llong *d)
{
int i,u,v,w,len;
node tmp;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++) d[i]=inf;
d[s]=0;
Q.push((node){0,s});
while(!Q.empty())
{
tmp=Q.top();
Q.pop();
u=tmp.x;
if(vis[u]) continue;
vis[u]=true;
len=GG[u].size();
for(i=0;i<len;i++)
{
v=GG[u][i].first;
w=GG[u][i].second;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
Q.push((node){d[v],v});
}
}
}
return;
}
struct edge{
int to,cap,rev;
};
vector<edge> G[tmax];
int level[tmax];
int iter[tmax];
void add(int from,int to,int cap)
{
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
return;
}
void bfs(int s)
{
memset(level,-1,sizeof(level));
queue<int> que;
level[s]=0;
que.push(s);
while(!que.empty())
{
int v=que.front();
que.pop();
for(int i=0;i<G[v].size();i++)
{
edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0)
{
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
return;
}
int dfs(int v,int t,int f)
{
if(v==t) return f;
for(int &i=iter[v];i<G[v].size();i++)
{
edge &e=G[v][i];
if(e.cap>0&&level[v]<level[e.to])
{
int d=dfs(e.to,t,min(f,e.cap));
if(d>0)
{
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int Dinic(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,inf_int))>0)
flow+=f;
}
}
int main()
{
int TT,i;
scanf("%d",&TT);
while(TT--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&xx[i],&yy[i],&cc[i]);
GG[xx[i]].push_back(Pii(yy[i],cc[i]));
}
dijk(1,dis);
for(i=1;i<=n;i++)
GG[i].clear();
for(i=1;i<=m;i++)
GG[yy[i]].push_back(Pii(xx[i],cc[i]));
dijk(n,_dis);
for(i=1;i<=m;i++)
{
if(dis[xx[i]]+cc[i]+_dis[yy[i]]==dis[n])
add(xx[i],yy[i],cc[i]);
}
cout<<Dinic(1,n)<<endl;
for(i=1;i<=n;i++)
{
GG[i].clear();
G[i].clear();
}
}
return 0;
}