首先我们将题目所求转化一下,变成求相邻的三个点对答案的贡献。
①先说我65分的做法:
枚举不相邻的两个点,然后枚举有几个点能成为他俩的中间点为
(其实相当于缩小了询问范围)
之后,对于能作为中间点的每一个点,分别去掉他;然后对于所询问的点跑单源最短路;那么他两边的点对答案的贡献就是
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
#define M 2005
#define pb push_back
using namespace std;
vector<int> q[M][M];
int tot,d[M],v[M],ans[M],inq[M],n,m,D[M],a[M][M],h[M];
struct edge
{
int y,ne;
}e[M*100];
void SPFA(int s,int k)
{
for (int i=1;i<=n;i++)
d[i]=inf;
d[s]=0;
queue<int> q;
q.push(s);
inq[s]=1;
while (!q.empty())
{
int x=q.front();
q.pop();
inq[x]=0;
for (int i=h[x];i;i=e[i].ne)
{
int y=e[i].y;
if (y==k) continue;
if (d[y]>d[x]+1)
{
d[y]=d[x]+1;
if (!inq[y])
q.push(y),inq[y]=1;
}
}
}
}
void Addedge(int x,int y)
{
e[++tot].y=y;
e[tot].ne=h[x];
h[x]=tot;
}
void spfa(int s)
{
for (int i=1;i<=n;i++)
d[i]=D[i]=inf,inq[i]=0,v[i]=0;
d[s]=D[s]=0;
queue<int> q;
q.push(s);
inq[s]=1;
while (!q.empty())
{
int x=q.front();
inq[x]=0;
q.pop();
for (int i=h[x];i;i=e[i].ne)
{
int y=e[i].y;
if (d[y]>d[x]+1)
{
if (d[x]==1&&!v[y])
{
v[y]=x;
continue;
}
d[y]=d[x]+1;
if (v[y]!=x) D[y]=d[y];
if (!inq[y])
inq[y]=1,q.push(y);
}
}
}
for (int i=1;i<=n;i++)
if (v[i]&&d[i]>2)
ans[v[i]]+=(d[i]-2);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Addedge(x,y);
Addedge(y,x);
a[x][y]=a[y][x]=1;
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<i;j++)
{
if (a[i][j]) continue;
int cnt=0,p;
for (int k=1;k<=n;k++)
{
if (a[i][k]&&a[j][k])
p=k,cnt+=1;
}
if (cnt==1)
q[p][i].pb(j);
}
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
if (q[i][j].size())
{
SPFA(j,i);
for (int k=0;k<q[i][j].size();k++)
ans[i]+=(d[q[i][j][k]]-2);
}
}
for (int i=1;i<=n;i++)
printf("%d\n",ans[i]);
cout<<endl;
/*
for (int i=1;i<=n;i++)
spfa(i);
for (int i=1;i<=n;i++)
printf("%d\n",ans[i]/2);
*/
return 0;
}
(注释掉的部分是我一开始写95分做法,写的有漏洞。。)
②再说95分的做法:
我们可以枚举三元组中的一头
对于直接与
这个如何实现呢?
距离
注意只要一求出
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#define mp make_pair
#define pa pair<int,int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define M 2005
#define pb push_back
using namespace std;
vector<int> q[M][M];
int from[M][2],d[M][2];
struct data
{
int v,k;
};
int tot,v[M],ans[M],inq[M],n,m,D[M],a[M][M],h[M];
struct edge
{
int y,ne;
}e[M*100];
void Addedge(int x,int y)
{
e[++tot].y=y;
e[tot].ne=h[x];
h[x]=tot;
}
void bfs(int s)
{
for (int i=1;i<=n;i++)
from[i][0]=from[i][1]=-1;
d[s][0]=d[s][1]=from[s][1]=from[s][0]=0;
queue<pa> q;
for (int i=h[s];i;i=e[i].ne)
{
int y=e[i].y;
from[y][0]=y;
d[y][0]=1;
q.push(mp(y,0));
}
while (!q.empty())
{
pa x=q.front();
q.pop();
for (int i=h[x.fi];i;i=e[i].ne)
{
int y=e[i].y;
if (from[y][0]==-1)
{
from[y][0]=from[x.fi][x.se];
d[y][0]=d[x.fi][x.se]+1;
q.push(mp(y,0));
}
else if (from[y][1]==-1&&!a[y][s]&&from[y][0]!=from[x.fi][x.se])
{
from[y][1]=from[x.fi][x.se];
d[y][1]=d[x.fi][x.se]+1;
q.push(mp(y,1));
}
}
}
for (int i=h[s];i;i=e[i].ne)
{
int y=e[i].y;
for (int j=h[y];j;j=e[j].ne)
if (e[j].y!=s&&from[e[j].y][0]==y)
ans[y]+=(d[e[j].y][1]-d[e[j].y][0]);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Addedge(x,y);
Addedge(y,x);
a[x][y]=a[y][x]=1;
}
for (int i=1;i<=n;i++)
bfs(i);
for (int i=1;i<=n;i++)
printf("%d\n",ans[i]/2);
return 0;
}
原文地址:http://blog.csdn.net/regina8023/article/details/45814805