题意
有一个好兄弟和好兄弟的好妹妹在两个城市,现在给你n个城市,m个单向道路(重点,此信息在输入数据的提示里,我一开始没读仔细,wa卡爆了【while there may have no road from b to a】)
问你有几种情况在每条路只通过一次的情况下有几种方式到达好妹妹的城市。2<=n<=1000, 0<=m<=100000
思路
先spfa正着搜start到各个点的最短路(存dp1[]),在spfa反着搜end到各个点的最短路(存dp2[])。
因为是有向图,所以先存一个图a->b,用于start到各个点的最短路,然后另存一个图b->a,用于end到各个点的最短路
用dp[i]+dp[j]+边长ij==最短路来确定是否这条边是最短路上的边。(毕竟最短路也有好几条)然后直接存进dinic里,流量是1。
spfa的模板
void spfa(int st,int x){
mindis[st][x]=0;
mem(vis,0);
queue<int>q;
q.push(st);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=head1[u];~i;i=edge1[i].next){
int v=edge1[i].to,w=edge1[i].c;
if(mindis[u][x]+w<mindis[v][x]){
mindis[v][x]=mindis[u][x]+w;
if(!vis[v]){
q.push(v);vis[v]=1;
}
}
}
}
}
dinic(复杂度o(n*m*m))的模板
int bfs(){
queue<int>q;
q.push(s);
for(int i=1;i<N;i++){dis[i]=inf;}
dis[s]=0;
while(!q.empty()){
int h=q.front(),i;q.pop();
for(i=head[h];~i;i=edge[i].next){
int v=edge[i].to;
if(edge[i].c>edge[i].flow && dis[v]==inf){
dis[v]=dis[h]+1;q.push(v);
}
}
}
return dis[t]<inf;
}
int dfs(int x,int maxflow){
if(x==t || maxflow==0){
return maxflow;
}
int flow=0,i,f;
for(i=cur[x];~i;i=edge[i].next){
cur[x]=i;
int v=edge[i].to;
if(dis[v]==(dis[x]+1) && edge[i].c>edge[i].flow){
f=dfs(v,min(maxflow,edge[i].c-edge[i].flow));
edge[i].flow+=f;
edge[i^1].flow-=f;
flow+=f;
maxflow-=f;
if(maxflow==0){break;}
}
}
return flow;
}
int dinic(){
int flow=0;
while(bfs()){
memcpy(cur,head,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
这题的ac代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 99999999
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
const double pi=acos(-1.0);
const int N=1e3+10,M=2e5+10;
struct node{
int to,next,c,flow;
}edge[M],edge2[M],edge1[M];
int cur[N],head[N],dis[N],tot,head2[N],tot2,head1[N],tot1;
int n,m,s,t;
int mindis[N][2];
void inint(){
tot=0;tot2=0;tot1=0;
for(int i=0;i<N;i++){
head[i]=head2[i]=head1[i]=-1;
mindis[i][0]=mindis[i][1]=99999999;
}
}
void add(int u,int v,int c){
edge[tot].to=v;edge[tot].c=c;edge[tot].flow=0;
edge[tot].next=head[u];head[u]=tot++;
edge[tot].to=u;edge[tot].c=0;edge[tot].flow=0;
edge[tot].next=head[v];head[v]=tot++;
}
void add2(int u,int v,int w){
edge1[tot1].to=v;edge1[tot1].c=w;
edge1[tot1].next=head1[u];head1[u]=tot1++;
edge2[tot2].to=u;edge2[tot2].c=w;
edge2[tot2].next=head2[v];head2[v]=tot2++;
}
int bfs(){
queue<int>q;
q.push(s);
for(int i=1;i<N;i++){dis[i]=inf;}
dis[s]=0;
while(!q.empty()){
int h=q.front(),i;q.pop();
for(i=head[h];~i;i=edge[i].next){
int v=edge[i].to;
if(edge[i].c>edge[i].flow && dis[v]==inf){
dis[v]=dis[h]+1;q.push(v);
}
}
}
return dis[t]<inf;
}
int dfs(int x,int maxflow){
if(x==t || maxflow==0){
return maxflow;
}
int flow=0,i,f;
for(i=cur[x];~i;i=edge[i].next){
cur[x]=i;
int v=edge[i].to;
if(dis[v]==(dis[x]+1) && edge[i].c>edge[i].flow){
f=dfs(v,min(maxflow,edge[i].c-edge[i].flow));
edge[i].flow+=f;
edge[i^1].flow-=f;
flow+=f;
maxflow-=f;
if(maxflow==0){break;}
}
}
return flow;
}
int dinic(){
int flow=0;
while(bfs()){
memcpy(cur,head,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
int vis[N];
void spfa2(int st,int x){
mindis[st][x]=0;
mem(vis,0);
queue<int>q;
q.push(st);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head2[u];~i;i=edge2[i].next){
int v=edge2[i].to,w=edge2[i].c;
if(mindis[u][x]+w<mindis[v][x]){
mindis[v][x]=mindis[u][x]+w;
if(!vis[v]){
q.push(v);vis[v]=1;
}
}
}
}
}
void spfa(int st,int x){
mindis[st][x]=0;
mem(vis,0);
queue<int>q;
q.push(st);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head1[u];~i;i=edge1[i].next){
int v=edge1[i].to,w=edge1[i].c;
if(mindis[u][x]+w<mindis[v][x]){
mindis[v][x]=mindis[u][x]+w;
if(!vis[v]){
q.push(v);vis[v]=1;
}
}
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
inint();
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int v,w,u;
scanf("%d%d%d",&u,&v,&w);
add2(u,v,w);
}
scanf("%d%d",&s,&t);
spfa(s,0);
spfa2(t,1);
//cout<<mindis[t][0]<<mindis[s][1]<<endl;
for(int u=1;u<=n;u++){
for(int i=head1[u];~i;i=edge1[i].next){
int v=edge1[i].to,w=edge1[i].c;
if(mindis[u][0]+mindis[v][1]+w==mindis[t][0]){
add(u,v,1);//cout<<u<<v<<endl;
}
}
}
printf("%d
",dinic());
}
}
这题容易wa和tle的注意事项
tle一边就是你数组开小,wa可能是初始距离开小,或者是你题意读错,有向边看成无向图。。。