标签:
从城市A到B,每次都走最短路,但每条边最多走一次,能够走多少次
曾做过一次这种题。建最短路树,跑SPFA
值得注意的是,如果跑dij的时候不建立永久标号,会导致最短路树出错
spfa要不停的进行松弛操作,同理不能这样建最短路树。看网上代码spfa都是正着反着跑两遍spfa,然后判断dis1[u]+dis2[v]+w==dis[B]是否成立。若成立,则u,v为最短路上的边
把网上的和我的都交了一遍,我的更快*_*
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1008;
const int maxm=100008;
const int INF=0x7f7f7f7f;
struct shit{
int v,w;
bool operator<(const shit &a) const
{
return w>a.w;
}
};
struct fuck{
int u,v,cap,next;
}edge[maxm<<2];
vector<shit> g[maxn];
int dis[maxn];
vector<int> distree[maxn];
bool vis[maxn];
int head[maxn];
int tol;
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol].cap=w;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].u=v;
edge[tol].v=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
int last;
int dep[maxn],gap[maxn];
void bfs(int sour,int sink)
{
queue<int> q;
int i,u,v;
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
q.push(sink);dep[sink]=0;gap[0]=1;
while(!q.empty())
{
u=q.front();q.pop();
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(dep[v]==-1&&edge[i].cap==0)
{
dep[v]=dep[u]+1;
q.push(v);
gap[dep[v]]++;
}
}
}
}
int sap(int sour,int sink,int n)
{
bfs(sour,sink);
int max_flow=0,top=0,i,u;
int S[maxn],cur[maxn];
for(i=0;i<=n;i++)
cur[i]=head[i];
u=sour;
while(dep[u]<last)
{
if(u==sink)
{
int temp=INF,inser;
for(i=0;i<top;i++)
if(edge[S[i]].cap<temp)
{
temp=edge[S[i]].cap;
inser=i;
}
for(i=0;i<top;i++)
{
edge[S[i]].cap-=temp;
edge[S[i]^1].cap+=temp;
}
max_flow+=temp;
top=inser;
u=edge[S[top]].u;
}
if(u!=sink&&gap[dep[u]-1]==0) break;
for(i=cur[u];i!=-1;i=edge[i].next)
if(edge[i].cap>0&&dep[u]==dep[edge[i].v]+1)
break;
if(i!=-1)
{
cur[u]=i;
S[top++]=i;
u=edge[i].v;
}
else
{
int mi=last;
for(i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap>0&&dep[edge[i].v]<mi)
{
mi=dep[edge[i].v];
cur[u]=i;
}
gap[dep[u]]--;
dep[u]=mi+1;
gap[dep[u]]++;
if(u!=sour) u=edge[S[--top]].u;
}
}
return max_flow;
}
void dfs(int u)
{
int i,v;
vis[u]=true;
last++;
for(i=0;i<distree[u].size();i++)
{
v=distree[u][i];
addedge(u,v,1);
if(!vis[v]) dfs(v);
}
}
int dij(int sour,int sink)
{
bool done[maxn];
priority_queue<shit> q;
int i,u,v,w;
shit pp;
pp.v=sour;pp.w=0;
q.push(pp);
memset(dis,INF,sizeof(dis));
memset(done,false,sizeof(done));
dis[sour]=0;
while(!q.empty())
{
pp=q.top();q.pop();
u=pp.v;
if(done[u]) continue;//永久标号没有wa数发
done[u]=true;
for(i=0;i<g[u].size();i++)
{
v=g[u][i].v;w=g[u][i].w;
if(dis[v]==dis[u]+w)
distree[v].push_back(u);
else if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pp.v=v;pp.w=dis[v];
q.push(pp);
distree[v].clear();
distree[v].push_back(u);
}
}
}
return dis[sink];
}
int main()
{
int i,j,t,u,v,w,n,m;
int sour,sink;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
shit pp;
init();
for(i=1;i<=n;i++)
{
g[i].clear();
distree[i].clear();
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
pp.v=v;pp.w=w;
g[u].push_back(pp);//曾建立无向边wa数发
}
scanf("%d%d",&sour,&sink);
int bitch=dij(sour,sink);
if(bitch==INF)
{
printf("0\n");
continue;
}
memset(vis,false,sizeof(vis));
last=0;
dfs(sink);
bitch=sap(sink,sour,n);
printf("%d\n",bitch);
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/bitch1319453/p/4776971.html