题目:http://acm.hdu.edu.cn/showproblem.php?pid=2833
题意:给定无向图,求两条最短路A->B,C->D,问这两条最短路的公共点最多有多少个
思路:1:floyd预处理所有点对最短路:
2:记忆化搜索:
首先A->B的最短路径,可以形成一棵有根树,
沿着A->B的最短路径形成的树,从A开始搜索,
dp[u],表示从u->B,两条最短路的最多公共定点数
if(edge(u->v)在A->B和C->D最短路径树上)dp[u]=max(dp[u],dp[v]+1);
else dp[u]=max(dp[u],dp[v]);
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=310;
const int M=310*310*2;
const int INF=1<<30;
int map[N][N];
int dp[N];
int vis[N];
inline int min(int a,int b)
{
return a<b?a:b;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
struct Edge
{
int to,next,w;
}e[M];
int total,head[N];
void add_edges(int from,int to,int w)
{
e[total].to=to,e[total].next=head[from],e[total].w=w,head[from]=total++;
}
void init()
{
total=0;memset(head,-1,sizeof(head));
}
void floyd(int n)
{
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
if(map[i][k]==INF)continue;
for(int j=0;j<n;j++)
{
if(map[k][j]==INF)continue;
map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
}
}
}
}
int s1,t1,s2,t2;
inline int f(int u)
{
if(map[s2][u]==INF||map[u][t2]==INF||map[s2][t2]!=map[s2][u]+map[u][t2])return 0;
return 1;
}
void dfs(int u)
{
int ans=0;
vis[u]=1;
int cnt=0;
int flag=f(u);
if(u==t1)
{
dp[u]=flag;
return ;
}
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(map[v][t1]==INF)continue;
if(map[u][t1]==map[v][t1]+e[i].w)
{
if(flag&&((map[u][t2]==map[v][t2]+e[i].w)||u==t2))cnt=1;
else cnt=0;
if(vis[v])
{
ans=max(ans,dp[v]+cnt);
}
else
{
dfs(v);
ans=max(ans,dp[v]+cnt);
}
}
}
if(!ans&&flag)ans=1;////表示u是第一个公共点
dp[u]=ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF,n||m)
{
init();
for(int i=0;i<n;i++)
{
map[i][i]=0;
for(int j=i+1;j<n;j++)
{
map[i][j]=map[j][i]=INF;
}
}
for(int i=0;i<m;i++)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);a--;b--;
add_edges(a,b,c);add_edges(b,a,c);
map[a][b]=map[b][a]=min(map[a][b],c);
}
floyd(n);
memset(vis,0,sizeof(vis));
scanf("%d%d%d%d",&s1,&t1,&s2,&t2);s1--;t1--;s2--;t2--;
/*for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
printf("%d,",map[i][j]);
}printf("\n");
}*/
if(map[s1][t1]==INF||map[s2][t2]==INF)
{
//printf("line1\n");
printf("0\n");continue;
}
dfs(s1);
//for(int i=0;i<n;i++){printf("%d--%d,",i+1,dp[i]);}
printf("%d\n",dp[s1]);
}
return 0;
}
p[v]);