题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416
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
不要真诚不干涉。
喜欢那个节目,现在明星也参加一个节目,但它发生在城市A和B之间。Starvae在城市A和女孩在城市B。每次Starvae可以到达城市B,并与他喜欢的女孩做数据。但有两个问题,一个是星华必须在最短的时间内到达B,据说他必须走最短的路。其他是没有道路可以采取不止一次。而城市之星去世可以不止一次。
因此,在一个好的RP下,Starvae可能有很多机会到达城市B。
但他不知道有多少机会,他最多能与他喜欢的女孩做数据。你能帮starva吗?
输入
第一行是表示案例编号的整数 T。(1<_T<#65)
对于每种情况下,第一行中有两个整数 n 和 m(2<\n_lt;#1000,0_lt;_m_lt;#100000)是城市数,m 是道路数。
然后跟随 m 行,每行有三个整数 a、b、c、(1_lt;_a,b_lt;n,0_lt;c_lt;_lt;_lt;_1000)表示有一条从 a 到 b 的路,其距离为 c,而从 b 到 a 可能没有
道路。可能有一条路从一条路到一条路,但你可以忽略它。如果从 a 到 b 有两条道路,则它们是不同的。最后是一条包含两个整数 A 和 B(1_lt;#A,B_lt;_N,A!=B)的行,表示城市 A
和城市 B 的数量。每个案例之间可能存在一些空白行。
输出
输出一个整数的线,意味着星形最多只能得到的机会。
题意其实就是让你求有几个最短路径。
首先我们需要清楚一个定理,如果一个边是最短路上的边,那么一定满足dis[e.from]+e.dis=dis[e.to];
之后就很好写了,也很经典了,
首先跑一个最短路,求出满足dis[e.from]+e.dis=dis[e.to]的边,即最短路上的边。
然后对每条最短路上的边建最大流边,容量为1,求出最大流即为结果。
不过最短路要用基于最小堆的DIjkstra算法实现,SPFA会超时。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e5+7;
const int maxm=1e5+7;
struct Edge{
int from,to;
LL val;
};
struct HeapNode{
LL d;
int u;
bool operator < (const HeapNode & rhs) const{
return d > rhs.d;
}
};
struct Dijstra{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
bool used[maxn];
LL d[maxn];
int p[maxn];
void init(int n){
this->n = n;
for(int i=0;i<=n;++i) G[i].clear();
edges.clear();
memset(used,0,sizeof(used));
}
void Addedge(int from,int to ,LL dist){
edges.push_back((Edge){from,to,dist});
m = edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s){
priority_queue<HeapNode> Q;
for(int i=0;i<=n;++i) d[i]=INF;
d[s]=0;
Q.push((HeapNode){0,s});
while(!Q.empty()){
HeapNode x =Q.top();Q.pop();
int u =x.u;
if(used[u])
continue;
used[u]= true;
for(int i=0;i<G[u].size();++i){
Edge & e = edges[G[u][i]];
if(d[e.to] > d[u] + e.val){
d[e.to] = d[u] +e.val;
p[e.to] = G[u][i];
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
}Dijk;
const int MAXN=1010;
const int MAXM=200010;
struct Node{
int from,to,next;
int cap;
};
struct SAP_MaxFlow{
int n,m;
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];
Node edge[MAXM];
void init(int N){
this->n = N;
this->tol=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,int w){
edge[tol].from=u;edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
edge[tol].from=v;edge[tol].to=u;edge[tol].cap=0;edge[tol].next=head[v];head[v]=tol++;
}
void BFS(int start,int end)
{
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0]=1;
int que[MAXN];
int front,rear;
front=rear=0;
dep[end]=0;
que[rear++]=end;
while(front!=rear){
int u=que[front++];
if(front==MAXN)front=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(dep[v]!=-1)continue;
que[rear++]=v;
if(rear==MAXN)rear=0;
dep[v]=dep[u]+1;
++gap[dep[v]];
}
}
}
int SAP(int start,int end)
{
int res=0;
BFS(start,end);
int cur[MAXN];
int S[MAXN];
int top=0;
memcpy(cur,head,sizeof(head));
int u=start;
int i;
while(dep[start]<n){
if(u==end){
int temp=INF;
int inser;
for(i=0;i<top;i++)
if(temp>edge[S[i]].cap){
temp=edge[S[i]].cap;
inser=i;
}
for(i=0;i<top;i++){
edge[S[i]].cap-=temp;
edge[S[i]^1].cap+=temp;
}
res+=temp;
top=inser;
u=edge[S[top]].from;
}
if(u!=end&&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].to]+1)
break;
if(i!=-1){
cur[u]=i;
S[top++]=i;
u=edge[i].to;
}
else{
int min=n;
for(i=head[u];i!=-1;i=edge[i].next){
if(edge[i].cap==0)continue;
if(min>dep[edge[i].to]){
min=dep[edge[i].to];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=min+1;
++gap[dep[u]];
if(u!=start)u=edge[S[--top]].from;
}
}
return res;
}
}sap;
int n,m,s,t;
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
Dijk.init(n);
sap.init(n);
for(int i = 0;i<m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Dijk.Addedge(u,v,w);
}
scanf("%d%d",&s,&t);
Dijk.dijkstra(s);
for(int i = 0;i<m;++i){
Edge e=Dijk.edges[i];
if(Dijk.d[e.from]+e.val==Dijk.d[e.to]){
sap.AddEdge(e.from,e.to,1);
}
}
printf("%d\n",sap.SAP(s,t));
}
return 0;
}