(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
目录
题意:传送门
原题目描述在最下面。
给定一个n个节点,m条带权单向边的图,问从st到ed的最短路径有多少条。(路径不能重复
思路:
可行解:
要建一个正向图和反向图,分别跑出从起点
st
s
t
和终点
ed
e
d
到各个点的最短路径。
然后枚举每条边,判断这条边是不是最短路路径上的边,如果是就在给两个端点连一条容量为
1
1
流量为的边。然后从
st
s
t
到
ed
e
d
跑一遍最大流就可以了。
好吧,这方法比较麻烦。。。可以只跑一次最短路。
某种解:
只预处理处以终点 ed e d 为起点的最短路 dis[] d i s [ ] 。然后从起点开始 dfs d f s 搜索判断每条边是不是此最短路上的边。如果是,就把两端点连一条流量为 1 1 <script type="math/tex" id="MathJax-Element-170">1</script>的边。然后跑最大流。
我ta丫疯狂wa,就是过不了,不知道为什么。但是有人可以过,我去。。。难受的一批
AC代码:
#include<bits/stdc++.h>
#define fuck(x) cout<<"* "<<x<<"\n"
using namespace std;
typedef long long LL;
const int N = 1e4+5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
struct lh{
int u,w;
lh(){}
lh(int a,int b){u=a,w=b;}
bool operator <(const lh &a)const{
return w>a.w;
}
};
struct node{
int v,w,nex;
node(){}
node(int b,int c,int d){v=b,w=c,nex=d;}
}edge[N*20],rev[N*20];
struct lp{
int to,w,nex;
lp(){}
lp(int a,int b,int c){to=a;w=b;nex=c;}
}cw[N*40];
int n,m,tot,dis[N],now[N],head[N],vis[N],revhead[N],revtot;
int st,ed,cnt,first[N],level[N];
void dij(){//以终点为起点跑dij
memset(vis,0,sizeof(vis));
dis[ed]=0;
priority_queue<lh>Q;
Q.push(lh(ed,0));
while(!Q.empty()){
lh b = Q.top();Q.pop();
int u = b.u;
if(vis[u])continue;
vis[u]=1;
for(int i=revhead[u];~i;i=rev[i].nex){
int v = rev[i].v,w=rev[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
Q.push(lh(v,dis[v]));
}
}
}
}
void dij2(){//以起点最起点跑dij
memset(vis,0,sizeof(vis));
now[st]=0;
priority_queue<lh>Q;
Q.push(lh(st,0));
while(!Q.empty()){
lh b = Q.top();Q.pop();
int u = b.u;
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];~i;i=edge[i].nex){
int v = edge[i].v,w=edge[i].w;
if(now[v]>now[u]+w){
now[v]=now[u]+w;
Q.push(lh(v,now[v]));
}
}
}
}
inline void add_dij(int u,int v,int c){//建立正向图和反向图
edge[++tot]=node(v,c,head[u]);
head[u]=tot;
rev[++revtot]=node(u,c,revhead[v]);
revhead[v]=revtot;
}
inline void add_edge(int u,int v,int c){//最大流建图
cw[++cnt]=lp(v,c,first[u]);
first[u]=cnt;
cw[++cnt]=lp(u,0,first[v]);
first[v]=cnt;
}
inline bool bfs(){
memset(level,-1,sizeof(level));
level[ed]=0;
queue<int>Q;
Q.push(ed);
while(!Q.empty()){
int u = Q.front();Q.pop();
for(int i=first[u];~i;i=cw[i].nex){
int v = cw[i].to;
if(level[v]==-1&&cw[i^1].w){
level[v]=level[u]+1;
Q.push(v);
}
}
}
return level[st]!=-1;
}
int dinic(int u,int flow){
if(u==ed||flow==0)return flow;
int use=0,w;
for(int i=first[u];~i;i=cw[i].nex){
int v = cw[i].to;
if(level[v]+1==level[u]&&cw[i].w){
w = dinic(v,min(flow-use,cw[i].w));
cw[i].w-=w;cw[i^1].w+=w;
use+=w;
if(use==flow)return flow;
}
}
return use;
}
inline void init(){//初始化
memset(head,-1,sizeof(head));
memset(revhead,-1,sizeof(revhead));
memset(first,-1,sizeof(first));
cnt=tot=revtot=-1;
}
int main(){
int tim;
scanf("%d",&tim);
while(tim--){
scanf("%d%d",&n,&m);
init();
for(int i=0,u,v,c;i<m;++i){
scanf("%d%d%d",&u,&v,&c);
add_dij(u,v,c);
}
scanf("%d%d",&st,&ed);
memset(dis,0x3f,sizeof(dis));
memset(now,0x3f,sizeof(now));
dij();dij2();
//printf("**%d\n",now[ed]);
//printf("dis[st] = %d\n", dis[st]);
for(int i=1;i<=n;++i){
for(int j=head[i];~j;j=edge[j].nex){
int v = edge[j].v;
if(now[i]+dis[v]+edge[j].w==dis[st]){
add_edge(i,v,1);
//printf("%d %d\n", i,v);
}
}
}
int ans=0;
while(bfs())ans+=dinic(st,INF);
printf("%d\n", ans);
}
return 0;
}
原题目描述:
Problem Description
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it’s said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don’t know how many chances at most he can make a data with the girl he likes . Could you help starvae?
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0 < c < = 1000)it means there is a road from a to b and it’s distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
Output
Output a line with a integer, means the chances starvae can get at most.
Sample Input
3
7 8
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
5 7 1
6 7 1
1 7
6 7
1 2 1
2 3 1
1 3 3
3 4 1
3 5 1
4 6 1
5 6 1
1 6
2 2
1 2 1
1 2 2
1 2
Sample Output
2
1
1
Author
starvae@HDU
Source
HDOJ Monthly Contest – 2010.06.05