Path
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
n
n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed
1
1
1 and go along the shortest path to hers, indexed
n
n
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
)
T(1\leq T \leq10)
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
)
n,m(1\leq n,m\leq 10000)
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
≤
1
0
9
)
x,y,c(1\leq x,y\leq n,1\leq c\leq10^9)
x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed
x
x
x to
y
y
y of length
c
c
c.
Output
Print T T 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
Source
2019 Multi-University Training Contest 1
题意
- 就是给你一张图,每条边都有一个权值,问删去一些边使得最短路径长度变长的最小花费是多少,花费为所有删去的边的权值之和
题解
- 首先可以 d i j k s t r a dijkstra dijkstra跑出节点1到任意一个点的最短路径,根据这个 d i s dis dis数组可以找出所有可能作为最短路径的边,然后用这些边建一张新的图,显然如果存在从1到n的路径,显然最短路径不会增加,所以相当于求吧这张图一份为 2 2 2的最小代价,很容易想到最小割吧,所以在新建的图上跑 d i n i c dinic dinic就行了
- 自己的板子只跑了 46 m s 46ms 46ms,在所有提交的当中算是比较快的了
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e5+10; //注意每条边都有反向边
#define inf 0x3f3f3f3f
namespace IO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline bool read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror) return false;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x; return true;
}
inline bool read(ll &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror) return false;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x; return true;
}
inline bool read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror) return false;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x; return true;
}
inline bool read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror) return false;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0; return true;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i) {}; print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace IO;
long long dis[maxn];int head[maxn],id[maxn],tot,n,m;//id:当前弧优化,即记录可用的最远的那条边
struct node{
int to,next;long long w;
node(int a=0,long long b=0,int c=0){
to=a;w=b;next=c;
}
}edge[maxm];
void add_edge(int u,int v,long long w)
{
edge[++tot]=node(v,w,head[u]);
head[u]=tot;
}
bool bfs(int s,int t)
{
queue<int> que;que.push(s);
for(int i=1;i<=n;i++) dis[i]=0,id[i]=head[i];dis[s]=1; //注意这里的n的范围,不注意经常死循环
while(!que.empty()){
int cur=que.front();que.pop();
for(int i=head[cur];i!=-1;i=edge[i].next){
int nxt=edge[i].to;
if(edge[i].w&&!dis[nxt]){
dis[nxt]=dis[cur]+1;
que.push(nxt);
if(nxt==t) return 1;
}
}
}
return 0;
}
long long dfs(int cur,long long flow,int s,int t)
{
if(cur==t) return flow;
long long rest=flow;
for(int i=id[cur];i!=-1&&rest;i=edge[i].next){
id[cur]=i;
if(edge[i].w&&dis[edge[i].to]==dis[cur]+1){
long long f=dfs(edge[i].to,min(rest,edge[i].w),s,t);
edge[i].w-=f;
edge[i^1].w+=f;
rest-=f;
}
}
return flow-rest;
}
inline long long dinic(int s,int t)
{
long long maxflow=0,flow;
while(bfs(s,t)) while((flow=dfs(s,inf,s,t))) maxflow+=flow;
return maxflow;
}
struct nod{int v;long long w;};
vector<nod> vec[maxn];
void dijkstra(int s)
{
priority_queue<pair<long long,int>,vector<pair<long long,int> >,greater<pair<long long,int> > > que;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;que.push(pair<long long,int>(0,s));
while(!que.empty()){
pair<long long,int> cur=que.top();que.pop();
if(dis[cur.second]<cur.first) continue;
for(int i=0;i<vec[cur.second].size();i++){
nod nxt=vec[cur.second][i];
if(dis[nxt.v]>dis[cur.second]+nxt.w){
dis[nxt.v]=dis[cur.second]+nxt.w;
que.push(pair<long long,int>(dis[nxt.v],nxt.v));
}
}
}
}
void get_graph(int s) //构建最短路图
{
for(int i=1;i<=n;i++) {
for(int j=0;j<vec[i].size();j++){
if(dis[vec[i][j].v]==dis[i]+vec[i][j].w){
add_edge(i,vec[i][j].v,vec[i][j].w);
add_edge(vec[i][j].v,i,0);
}
}
}
}
int main()
{
//freopen("/Users/wzw/Desktop/ACM/1.in","r",stdin);
int t;read(t);
while(t--){
read(n);read(m);
for(int i=1;i<=n;i++) vec[i].clear(),head[i]=-1;tot=-1;
for(int i=1,u,v,w;i<=m;i++){
read(u);read(v);read(w);
vec[u].push_back(nod{v,w});
}
dijkstra(1);
get_graph(1);
printf("%lld\n",dinic(1,n));
}
}