码迷,mamicode.com
首页 > 其他好文 > 详细

【THOI 2012】 社交网络结构洞

时间:2015-05-18 08:59:44      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:thusc   oi   思路题   最短路   

A1364. 社交网络结构洞

首先我们将题目所求转化一下,变成求相邻的三个点对答案的贡献。

①先说我65分的做法:
枚举不相邻的两个点,然后枚举有几个点能成为他俩的中间点为cnt,如果cnt==0cnt>1,这两个点显然对答案没有贡献,那么把cnt==1的两个点加入询问中,并记录中间点。
(其实相当于缩小了询问范围)

之后,对于能作为中间点的每一个点,分别去掉他;然后对于所询问的点跑单源最短路;那么他两边的点对答案的贡献就是d[i][j]?2

#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分的做法:
我们可以枚举三元组中的一头s,跑SPFA。

对于直接与s相邻的点x,他能拓展出与s距离为2的点y,我们需要记录从s出发不经过x到达y的最短路,加入对x的贡献。(最后所有答案都/2

这个如何实现呢?

距离d数组多记录一维d[i][0],d[i][1]分别表示经过x和不经过x的最短路(这样做不会漏下,因为如果经过一个以上的x对答案没有贡献),from[i][0]=x,from[i][1]x,然后像跑SPFA一样求即可。
注意只要一求出d[i][j],之后一定不会更新了!因为队列中的d[][]是不降的!

#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;
}

【THOI 2012】 社交网络结构洞

标签:thusc   oi   思路题   最短路   

原文地址:http://blog.csdn.net/regina8023/article/details/45814805

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!