T1 Tyoj P3535 kshort
描述
有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m
给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。
输入格式
输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。
输出格式
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
测试样例1
输入
【样例输入1】
5 20 10 1 5
1 2 1
1 3 2
1 4 1
1 5 3
2 1 1
2 3 1
2 4 2
2 5 2
3 1 1
3 2 2
3 4 1
3 5 1
4 1 1
4 2 1
4 3 1
4 5 2
5 1 1
5 2 1
5 3 1
5 4 1
【样例输入2】
4 6 1 1 4
2 4 2
1 3 2
1 2 1
1 4 3
2 3 1
3 4 1
【样例输入3】
3 3 5 1 3
1 2 1
2 3 1
1 3 1
输出
【样例输出1】
1-2-4-3-5
【样例输出2】
1-2-3-4
【样例输出3】
No
备注
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路,排序如下:
序号 长度 路径 序号 长度 路径
1 3 1-2-3-5 9 5 1-2-3-4-5
2 3 1-2-5 10 5 1-2-4-3-5
3 3 1-3-5 11 5 1-2-4-5
4 3 1-4-3-5 12 5 1-3-4-5
5 3 1-4-5 13 6 1-3-2-5
6 3 1-5 14 6 1-3-4-2-5
7 4 1-4-2-3-5 15 6 1-4-3-2-5
8 4 1-4-2-5 16 8 1-3-2-4-5
【限制】
20%的数据满足:n
40%的数据满足:n
100%的数据满足:2
1 #include <algorithm> 2 #include <cstdio> 3 #include <queue> 4 5 const int INF(0x3f3f3f3); 6 const int N(566); 7 int n,m,k,a,b; 8 int hed[N],had[N],sumedge; 9 struct Edge { 10 int v,next,w; 11 Edge(int v=0,int next=0,int w=0):v(v),next(next),w(w){} 12 }edge[N*N][2]; 13 inline void ins(int u,int v,int w) 14 { 15 edge[++sumedge][0]=Edge(v,hed[u],w); hed[u]=sumedge; 16 edge[ sumedge][1]=Edge(u,had[v],w); had[v]=sumedge; 17 } 18 19 inline void read(int &x) 20 { 21 x=0; register char ch=getchar(); 22 for(;ch>'9'||ch<'0';) ch=getchar(); 23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 24 } 25 26 int dis[N]; 27 bool inq[N]; 28 void SPFA(int s) 29 { 30 std::queue<int>que; 31 for(int i=1; i<=n; ++i) 32 dis[i]=INF; dis[s]=0; 33 que.push(s); 34 for(int u,v; !que.empty(); ) 35 { 36 u=que.front(); que.pop(); inq[u]=0; 37 for(int i=had[u]; i; i=edge[i][1].next) 38 { 39 v=edge[i][1].v; 40 if(dis[v]>dis[u]+edge[i][1].w) 41 { 42 dis[v]=dis[u]+edge[i][1].w; 43 if(!inq[v]) que.push(v),inq[v]=1; 44 } 45 } 46 } 47 } 48 49 #define min(a,b) (a<b?a:b) 50 51 struct Node { 52 int g,now; 53 bool vis[N]; 54 std::vector<int>vec; 55 bool operator < (const Node x)const 56 { 57 return g+dis[now]>x.g+dis[x.now]; 58 } 59 }u,v; 60 bool cmp(Node x,Node y) 61 { 62 if(x.g!=y.g) return x.g<y.g; 63 int len=min(x.vec.size(),y.vec.size()); 64 for(int i=0;i<len;i++) 65 { 66 if(x.vec[i]<y.vec[i]) return 1; 67 else if(x.vec[i]>y.vec[i]) return 0; 68 } 69 return x.vec.size()<y.vec.size(); 70 } 71 72 void Astar(int s,int t,int k) 73 { 74 if(s==t) k++; int cnt=0; 75 u.now=s; u.g=0; u.vis[s]=1; u.vec.push_back(s); 76 std::priority_queue<Node>que; que.push(u); 77 std::vector<Node>ans; 78 for(; !que.empty(); ) 79 { 80 u=que.top(); que.pop(); 81 if(u.now==t) 82 { 83 if(++cnt>k&&u.g>ans[k-1].g) break; 84 ans.push_back(u); 85 } 86 for(int to,i=hed[u.now]; i; i=edge[i][0].next) 87 { 88 to=edge[i][0].v; 89 if(u.vis[to]) continue; 90 v=u; 91 v.now=to; 92 v.vis[to]=1; 93 v.vec.push_back(to); 94 v.g=u.g+edge[i][0].w; 95 que.push(v); 96 } 97 } 98 if(ans.size()<k) puts("No"); 99 else 100 { 101 sort(ans.begin(),ans.end(),cmp); 102 int len=ans[k-1].vec.size(); 103 for(int i=0;i<len-1;i++) 104 printf("%d-",ans[k-1].vec[i]); 105 printf("%d",ans[k-1].vec[len-1]); 106 } 107 } 108 109 int AC() 110 { 111 freopen("bzoj_1073.in","r",stdin); 112 freopen("bzoj_1073.out","w",stdout); 113 read(n),read(m),read(k),read(a),read(b); 114 for(int u,v,w; m--; ) 115 read(u),read(v),read(w),ins(u,v,w); 116 SPFA(b); Astar(a,b,k); 117 return 0; 118 } 119 120 int Hope=AC(); 121 int main(){;}
T2 BZOJ 1093: [ZJOI2007]最大半连通子图
Description
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,
则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图
中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。
Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
Sample Input
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
HINT
Source
考试是好傻、、Top_sort,非要记录每个数出现的个数噗噗
1 #include <algorithm> 2 #include <cstdio> 3 #include <queue> 4 5 const int N(100000+15); 6 const int M(1000000+5); 7 int n,m,mod,K,C; 8 int head[N][2],sumedge[2]; 9 struct Edge { 10 int v,next; 11 Edge(int v=0,int next=0):v(v),next(next){} 12 }edge[M][2]; 13 inline void ins(int op,int u,int v) 14 { 15 edge[++sumedge[op]] [op] = Edge(v,head[u][op]); 16 head[u] [op]=sumedge [op]; 17 } 18 19 inline void read(int &x) 20 { 21 x=0; register char ch=getchar(); 22 for(;ch>'9'||ch<'0';) ch=getchar(); 23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 24 } 25 26 #define min(a,b) (a<b?a:b) 27 #define max(a,b) (a>b?a:b) 28 29 int tim,dfn[N],low[N]; 30 int top,Stack[N],instack[N]; 31 int sumcol,col[N],point[N]; 32 void DFS(int u) 33 { 34 low[u]=dfn[u]= ++tim; 35 Stack[++top]=u; instack[u]=1; 36 for(int v,i=head[u][0]; i; i=edge[i][0].next) 37 { 38 v=edge[i][0].v; 39 if(!dfn[v]) DFS(v), low[u]=min(low[u],low[v]); 40 else if(instack[v]) low[u]=min(low[u],dfn[v]); 41 } 42 if(low[u]==dfn[u]) 43 { 44 col[u]=++sumcol; 45 point[sumcol]++; 46 for(; Stack[top]!=u; --top) 47 { 48 point[sumcol]++; 49 instack[Stack[top]]=0; 50 col[Stack[top]]=sumcol; 51 } 52 instack[u]=0; top--; 53 } 54 } 55 56 int rd[N],sum[N],inq[N]; 57 struct Node { 58 int now,sum; 59 }; 60 std::queue<Node>que; 61 62 int AC() 63 { 64 read(n),read(m),read(mod); 65 for(int u,v; m--; ) 66 read(u),read(v),ins(0,u,v); 67 for(int i=1; i<=n; ++i) 68 if(!dfn[i]) DFS(i); 69 70 for(int v,u=1; u<=n; ++u) 71 for(int i=head[u][0]; i; i=edge[i][0].next) 72 { 73 v=edge[i][0].v; 74 if(col[u]==col[v]) continue; 75 ins(1,col[u],col[v]); rd[col[v]]++; 76 } 77 Node u; 78 for(int i=1; i<=sumcol; ++i) 79 if(!rd[i]) 80 { 81 u.now=i,u.sum=point[i]; 82 que.push(u); 83 // sum[i]=point[i]; 84 // K=max(K,sum[i]); 85 } 86 for(Node u,v; !que.empty(); ) 87 { 88 u=que.front(); que.pop(); 89 if(u.sum>K) K=u.sum,C=1; 90 else if(u.sum==K) C=(C+1)%mod; 91 for(int i=head[u.now][1]; i; i=edge[i][1].next) 92 { 93 v=u; 94 v.now=edge[i][1].v; 95 v.sum+=point[v.now]; 96 que.push(v); 97 // else if(sum[v]>K) K=sum[v],C=1; 98 // else if(sum[v]==K) C=(C+1)%mod; 99 } 100 } 101 // std::sort(sum+1,sum+sumcol+1); 102 printf("%d %d ",K,C); 103 return 0; 104 } 105 /* 106 6 7 20070603 107 1 2 108 2 1 109 1 3 110 2 4 111 5 6 112 6 4 113 4 3 114 */ 115 int Hope=AC(); 116 int main(){;}
缩点后建新图(注意判重边),用Top_sort更新到这个点的最大K,和最大C,最后统计答案
1 #include <algorithm> 2 #include <cstdio> 3 #include <queue> 4 5 const int N(100000+15); 6 const int M(1000000+5); 7 int n,m,mod,K,C; 8 int head[N][2],sumedge[2]; 9 struct Edge { 10 int v,next; 11 Edge(int v=0,int next=0):v(v),next(next){} 12 }edge[M][2]; 13 inline void ins(int op,int u,int v) 14 { 15 edge[++sumedge[op]] [op] = Edge(v,head[u][op]); 16 head[u] [op]=sumedge [op]; 17 } 18 19 inline void read(int &x) 20 { 21 x=0; register char ch=getchar(); 22 for(;ch>'9'||ch<'0';) ch=getchar(); 23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 24 } 25 26 #define min(a,b) (a<b?a:b) 27 #define max(a,b) (a>b?a:b) 28 29 int tim,dfn[N],low[N]; 30 int top,Stack[N],instack[N]; 31 int sumcol,col[N],point[N]; 32 void DFS(int u) 33 { 34 low[u]=dfn[u]= ++tim; 35 Stack[++top]=u; instack[u]=1; 36 for(int v,i=head[u][0]; i; i=edge[i][0].next) 37 { 38 v=edge[i][0].v; 39 if(!dfn[v]) DFS(v), low[u]=min(low[u],low[v]); 40 else if(instack[v]) low[u]=min(low[u],dfn[v]); 41 } 42 if(low[u]==dfn[u]) 43 { 44 col[u]=++sumcol; 45 point[sumcol]++; 46 for(; Stack[top]!=u; --top) 47 { 48 point[sumcol]++; 49 instack[Stack[top]]=0; 50 col[Stack[top]]=sumcol; 51 } 52 instack[u]=0; top--; 53 } 54 } 55 56 inline bool cant_link(int u,int v) 57 { 58 for(int i=head[u][1]; i; i=edge[i][1].next) 59 if(edge[i][1].v==v) return true; 60 return false; 61 } 62 63 int rd[N],pre[N]; 64 std::queue<int>que; 65 struct Node { 66 int cnt,sum; 67 }node[N]; 68 69 int AC() 70 { 71 read(n),read(m),read(mod); 72 for(int u,v; m--; ) 73 read(u),read(v),ins(0,u,v); 74 for(int i=1; i<=n; ++i) 75 if(!dfn[i]) DFS(i); 76 for(int v,u=1; u<=n; ++u) 77 for(int i=head[u][0]; i; i=edge[i][0].next) 78 { 79 v=edge[i][0].v; 80 if(col[u]==col[v]) continue; 81 if(cant_link(col[u],col[v])) continue; 82 ins(1,col[u],col[v]); rd[col[v]]++; 83 } 84 for(int i=1; i<=sumcol; ++i) 85 if(!rd[i]) 86 { 87 que.push(i); 88 node[i].cnt=1; 89 node[i].sum=point[i]; 90 } 91 for(int u,v; !que.empty(); ) 92 { 93 u=que.front(); que.pop(); 94 for(int i=head[u][1]; i; i=edge[i][1].next) 95 { 96 v=edge[i][1].v; 97 if(node[v].sum<node[u].sum+point[v]) 98 { 99 node[v].cnt=node[u].cnt; 100 node[v].sum=node[u].sum+point[v]; 101 } 102 else if(node[v].sum==node[u].sum+point[v]) 103 node[v].cnt=(node[v].cnt+node[u].cnt)%mod; 104 if(--rd[v]==0) que.push(v); 105 } 106 } 107 for(int i=1; i<=sumcol; ++i) 108 if(node[i].sum>K) K=node[i].sum,C=node[i].cnt; 109 else if(node[i].sum==K) C=(C+node[i].cnt)%mod; 110 printf("%d %d ",K,C); 111 return 0; 112 } 113 114 int Hope=AC(); 115 int main(){;}
T3 Tyvj P2207 上学路线route
描述
可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校。直到有一天他们两人参加了学校的信息学奥林匹克竞赛小组才发现每天上学的乘车路线不一定是最优的。
可可:“很可能我们在上学的路途上浪费了大量的时间,让我们写一个程序来计算上学需要的最少时间吧!”
合肥市一共设有N个公交车站,不妨将它们编号为1…N的自然数,并认为可可和卡卡家住在1号汽车站附近,而他们学校在N号汽车站。市内有M条直达汽车路线,执行第i条路线的公交车往返于站点pi和qi之间,从起点到终点需要花费的时间为ti。(1
两个人坐在电脑前,根据上面的信息很快就编程算出了最优的乘车方案。然而可可忽然有了一个鬼点子,他想趁卡卡不备,在卡卡的输入数据中删去一些路线,从而让卡卡的程序得出的答案大于实际的最短时间。而对于每一条路线i事实上都有一个代价ci:删去路线的ci越大卡卡就越容易发现这个玩笑,可可想知道什么样的删除方案可以达到他的目的而让被删除的公交车路线ci之和最小。
[任务]
编写一个程序:
从输入文件中读取合肥市公交路线的信息;
计算出实际上可可和卡卡上学需要花费的最少时间;
帮助可可设计一个方案,删除输入信息中的一些公交路线,使得删除后从家到学校需要的最少时间变大,而被删除路线的ci和最小;向输出文件输出答案。
输入格式
输入文件中第一行有两个正整数N和M,分别表示合肥市公交车站和公交汽车路线的个数。以下M行,每行(第i行,总第(i+1)行)用四个正整数描述第i条路线:pi, qi, ti, ci;具体含义见上文描述。
输出格式
输出文件最多有两行。
第一行中仅有一个整数,表示从可可和卡卡家到学校需要的最短时间。
第二行输出一个整数C,表示Ci之和
测试样例1
输入
6 7
1 2 1 3
2 6 1 5
1 3 1 1
3 4 1 1
4 6 1 1
5 6 1 2
1 5 1 4
输出
2
5
备注
2
合肥市的公交网络十分发达,你可以认为任意两个车站间都可以通过直达或转车互相到达,当然如果在你提供的删除方案中,家和学校无法互相到达,那么则认为上学需要的最短为正无穷大:这显然是一个合法的方案。
粘一个最短路都能出错的Astar让大家笑一会。、、
1 #include <cstdio> 2 #include <queue> 3 4 const int INF(0x3f3f3f3f); 5 const int N(500+115); 6 const int M(124750+5); 7 int n,m,anscost; 8 int hed[N],had[N],sumedge; 9 struct Edge { 10 int v,next,t,c; 11 Edge(int v=0,int next=0,int t=0,int c=0):v(v),next(next),t(t),c(c){} 12 }edge[M][2]; 13 inline void ins(int u,int v,int t,int c) 14 { 15 edge[++sumedge][0]=Edge(v,hed[u],t,c); hed[u]=sumedge; 16 edge[ sumedge][1]=Edge(u,had[v],t,c); had[v]=sumedge; 17 } 18 19 inline void read(int &x) 20 { 21 x=0; register char ch=getchar(); 22 for(;ch>'9'||ch<'0';) ch=getchar(); 23 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 24 } 25 26 #define min(a,b) (a<b?a:b) 27 28 int dis[N]; 29 bool inq[N]; 30 void SPFA(int s) 31 { 32 std::queue<int>que; 33 for(int i=1; i<=n; ++i) 34 dis[i]=INF; dis[s]=0; 35 que.push(s); 36 for(int u,v; !que.empty(); ) 37 { 38 u=que.front(); que.pop(); inq[u]=0; 39 for(int i=had[u]; i; i=edge[i][1].next) 40 { 41 v=edge[i][1].v; 42 if(dis[v]>dis[u]+edge[i][1].t) 43 { 44 dis[v]=dis[u]+edge[i][1].t; 45 if(!inq[v]) que.push(v),inq[v]=1; 46 } 47 } 48 } 49 } 50 51 struct Node { 52 int g,now; 53 int cost; 54 bool operator < (const Node x)const 55 { 56 return g+dis[now]>x.g+dis[x.now]; 57 } 58 }u,v; 59 void Astar(int s,int t) 60 { 61 int cnt=0,mintim; 62 u.now=s; u.g=0; 63 u.cost=INF; 64 std::priority_queue<Node>que; que.push(u); 65 for(; !que.empty(); ) 66 { 67 u=que.top(); que.pop(); 68 if(u.now==t) 69 { 70 cnt++; 71 if(cnt==1) 72 { 73 mintim=u.g; 74 anscost=u.cost; 75 } 76 else if(u.g==mintim) anscost+=u.cost; 77 else break; 78 } 79 for(int to,i=hed[u.now]; i; i=edge[i][0].next) 80 { 81 to=edge[i][0].v; 82 v=u; 83 v.now=to; 84 v.g=u.g+edge[i][0].t; 85 v.cost=min(v.cost,edge[i][0].c); 86 que.push(v); 87 } 88 } 89 } 90 91 int AC() 92 { 93 int m; read(n),read(m); 94 for(int u,v,t,c,i=1; i<=m; ++i) 95 read(u),read(v),read(t),read(c),ins(u,v,t,c); 96 SPFA(n); Astar(1,n); 97 printf("%d %d",dis[1],anscost); 98 return 0; 99 } 100 101 int Hope=AC(); 102 int main(){;}
题解:找出最短路径,枚举每条使tim[1][u]+map[i].tim+tim[v][n]==tim[1][n]成立的边,新建图,跑最小割。
1 #include <cstring> 2 #include <cstdio> 3 4 const int INF(0x3f3f3f3f); 5 const int M(124750); 6 const int N(506+26); 7 8 inline void read(int &x) 9 { 10 x=0; register char ch=getchar(); 11 for(;ch>'9'||ch<'0';) ch=getchar(); 12 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 13 } 14 15 #define max(a,b) (a>b?a:b) 16 #define min(a,b) (a<b?a:b) 17 18 int tim[N][N],cost[N][N]; 19 struct Map { 20 int u,v,tim,cost; 21 Map(int u=0,int v=0,int tim=0,int cost=0): 22 u(u),v(v),tim(tim),cost(cost){} 23 }map[M]; 24 inline int Floyd(int n) 25 { 26 for(int k=1; k<=n; ++k) 27 for(int i=1; i<=n; ++i) 28 for(int j=1; j<=n; ++j) 29 tim[i][j]=min(tim[i][j],tim[i][k]+tim[k][j]); 30 return tim[1][n]; 31 } 32 33 int head[N],sumedge=1; 34 struct Edge { 35 int v,next,cost; 36 Edge(int v=0,int next=0,int cost=0): 37 v(v),next(next),cost(cost){} 38 }edge[N*N<<1]; 39 inline void ins(int u,int v,int cost) 40 { 41 edge[++sumedge]=Edge(v,head[u],cost); 42 head[u]=sumedge; 43 edge[++sumedge]=Edge(u,head[v],0); 44 head[v]=sumedge; 45 } 46 inline void Link_new_map(int n,int m) 47 { 48 for(int u,v,i=1; i<=m; ++i) 49 { 50 u=map[i].u; v=map[i].v; 51 if(tim[1][u]+map[i].tim+tim[v][n]==tim[1][n]) 52 ins(u,v,map[i].cost); 53 if(tim[1][v]+map[i].tim+tim[u][n]==tim[1][n]) 54 ins(v,u,map[i].cost); 55 } 56 } 57 58 int h,tail,que[N],deep[N]; 59 inline bool BFS(int s,int t) 60 { 61 for(int i=1; i<=t; ++i) 62 deep[i]=-1; deep[s]=0; 63 h=tail=0; que[tail++]=s; 64 for(int u,v; h<tail; h++) 65 { 66 u=que[h]; if(u==t) return 1; 67 for(int i=head[u]; i; i=edge[i].next) 68 { 69 v=edge[i].v; 70 if(deep[v]<0&&edge[i].cost>0) 71 { 72 deep[v]=deep[u]+1; 73 que[tail++]=v; 74 } 75 } 76 } 77 return false; 78 } 79 int DFS(int t,int u,int flow) 80 { 81 if(u==t||!flow) return flow; 82 int flux=0,lose; 83 for(int v,i=head[u]; i; i=edge[i].next) 84 { 85 v=edge[i].v; 86 if(deep[v]!=deep[u]+1||edge[i].cost<=0) continue; 87 lose=DFS(t,v,min(flow,edge[i].cost)); 88 flow-=lose; 89 flux+=lose; 90 edge[i].cost-=lose; 91 edge[i^1].cost+=lose; 92 if(!flow) return flux; 93 } 94 if(!flux) deep[u]=-1; 95 return flux; 96 } 97 inline int Dinic(int s,int t) 98 { 99 int ret=0; 100 for(; BFS(s,t); ) ret+=DFS(t,s,INF); 101 return ret; 102 } 103 104 int AC() 105 { 106 int n,m; read(n),read(m); 107 for(int i=1; i<=n; ++i) 108 for(int j=1; j<=n; ++j) 109 cost[i][j]=tim[i][j]=(i!=j)*INF; 110 for(int u,v,t,c,i=1; i<=m; ++i) 111 { 112 read(u),read(v),read(t),read(c); 113 tim[v][u]=tim[u][v]=t; 114 map[i]=Map(u,v,tim[u][v],c); 115 } 116 printf("%d ",Floyd(n)); 117 Link_new_map(n,m); 118 printf("%d ",Dinic(1,n)); 119 return 0; 120 } 121 122 int Hope=AC(); 123 int main(){;}
1 #include <cstring> 2 #include <cstdio> 3 #include <queue> 4 5 const int INF(0x3f3f3f3f); 6 const int M(124750); 7 const int N(506+26); 8 9 inline void read(int &x) 10 { 11 x=0; register char ch=getchar(); 12 for(;ch>'9'||ch<'0';) ch=getchar(); 13 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 14 } 15 16 #define max(a,b) (a>b?a:b) 17 #define min(a,b) (a<b?a:b) 18 19 int hed[N],sum,tim[N][2],inq[N]; 20 struct Map { 21 int u,v,tim,cost; 22 Map(int u=0,int v=0,int tim=0,int cost=0): 23 u(u),v(v),tim(tim),cost(cost){} 24 }map[M]; 25 struct E { 26 int v,next,tim; 27 E(int v=0,int next=0,int tim=0): 28 v(v),next(next),tim(tim){} 29 }e[N*N<<2]; 30 inline void insert(int u,int v,int tim) 31 { 32 e[++sum]=E(v,hed[u],tim); hed[u]=sum; 33 } 34 inline void SPFA(int n,int s,int op) 35 { 36 for(int i=1; i<=n; ++i) 37 tim[i][op]=INF,inq[i]=0; tim[s][op]=0; 38 std::queue<int>q; q.push(s); 39 for(int u,v; !q.empty(); ) 40 { 41 u=q.front(); q.pop(); inq[u]=0; 42 for(int i=hed[u]; i; i=e[i].next) 43 { 44 v=e[i].v; 45 if(tim[v][op]>tim[u][op]+e[i].tim); 46 { 47 tim[v][op]=tim[u][op]+e[i].tim; 48 if(!inq[v]) inq[v]=1,q.push(v); 49 } 50 } 51 } 52 } 53 54 int head[N],sumedge=1; 55 struct Edge { 56 int v,next,cost; 57 Edge(int v=0,int next=0,int cost=0): 58 v(v),next(next),cost(cost){} 59 }edge[N*N<<1]; 60 inline void ins(int u,int v,int cost) 61 { 62 edge[++sumedge]=Edge(v,head[u],cost); 63 head[u]=sumedge; 64 edge[++sumedge]=Edge(u,head[v],0); 65 head[v]=sumedge; 66 } 67 inline void Link_new_map(int n,int m) 68 { 69 for(int u,v,i=1; i<=m; ++i) 70 { 71 u=map[i].u; v=map[i].v; 72 if(tim[v][0]+map[i].tim+tim[u][1]==tim[n][0]) 73 ins(u,v,map[i].cost); 74 if(tim[u][0]+map[i].tim+tim[v][1]==tim[n][0]) 75 ins(v,u,map[i].cost); 76 } 77 } 78 79 int h,tail,que[N],deep[N]; 80 inline bool BFS(int s,int t) 81 { 82 for(int i=1; i<=t; ++i) 83 deep[i]=-1; deep[s]=0; 84 h=tail=0; que[tail++]=s; 85 for(int u,v; h<tail; h++) 86 { 87 u=que[h]; if(u==t) return 1; 88 for(int i=head[u]; i; i=edge[i].next) 89 { 90 v=edge[i].v; 91 if(deep[v]<0&&edge[i].cost>0) 92 { 93 deep[v]=deep[u]+1; 94 que[tail++]=v; 95 } 96 } 97 } 98 return false; 99 } 100 int DFS(int t,int u,int flow) 101 { 102 if(u==t||!flow) return flow; 103 int flux=0,lose; 104 for(int v,i=head[u]; i; i=edge[i].next) 105 { 106 v=edge[i].cost; 107 if(deep[v]!=deep[u]+1||edge[i].cost<=0) continue; 108 lose=DFS(t,v,min(flow,edge[i].cost)); 109 flow-=lose; 110 flux+=lose; 111 edge[i].cost-=lose; 112 edge[i^1].cost+=lose; 113 if(!flow) return flux; 114 } 115 if(!flux) deep[u]=-1; 116 return flux; 117 } 118 inline int Dinic(int s,int t) 119 { 120 int ret=0; 121 for(; BFS(s,t); ) ret+=DFS(t,s,INF); 122 return ret; 123 } 124 125 int AC() 126 { 127 int n,m; read(n),read(m); 128 for(int u,v,t,c,i=1; i<=m; ++i) 129 { 130 read(u),read(v),read(t),read(c); 131 insert(u,v,t);insert(v,u,t); 132 map[i]=Map(u,v,t,c); 133 } 134 SPFA(n,1,0); SPFA(n,n,1); 135 printf("%d ",tim[n][0]); 136 Link_new_map(n,m); 137 printf("%d ",Dinic(1,n)); 138 return 0; 139 } 140 141 int Hope=AC(); 142 int main(){;}