2016四川省赛 Floyd-Warshall

这题真的有毒
首先你忽略 N-M < 100 的条件你就gg吧
其次就算你知道了怎么做之后
还有可能因为写vector或者各种常数大的原因被卡

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const int MAXN = 1e5+205;

int N,M,Q;
struct Node{
    int to,nex;
}mip[MAXN*2], vic[MAXN*2];
int mp[MAXN]; int mot;
int vc[MAXN]; int vot;

int vis[MAXN];
int pre[MAXN];

int tag[MAXN]; 
int po[MAXN]; int po_cc; int cc;
void add1(int x,int y) {
    mip[mot].to = y; mip[mot].nex = mp[x]; mp[x] = mot++;
    mip[mot].to = x; mip[mot].nex = mp[y]; mp[y] = mot++;
}
void add2(int x,int y) {
    vic[vot].to = y; vic[vot].nex = vc[x]; vc[x] = vot++;
    vic[vot].to = x; vic[vot].nex = vc[y]; vc[y] = vot++;
}
map< pair<int,int>, int> mmp;
int dis[205][MAXN];
/*************LCA***************/
const int DEG=20;
int fa[MAXN][DEG];
int deg[MAXN];
void BFS(int rt) {
    queue<int> qq;
    deg[rt] = 0;
    fa[rt][0] = rt;
    qq.push(rt);
    while(!qq.empty()){
        int tmp = qq.front(); qq.pop();
        for(int i = 1; i < DEG; ++i)
            fa[tmp][i] = fa[fa[tmp][i-1]][i-1];
        for(int i = vc[tmp]; i !=-1; i = vic[i].nex) {
            int v = vic[i].to; if(v == fa[tmp][0]) continue;
            deg[v] = deg[tmp]+1; fa[v][0]=tmp;
            qq.push(v);
        }
    }
}
int LCA(int u,int v) {
    if(deg[u] > deg[v]) swap(u,v);
    int hu = deg[u], hv = deg[v];
    int tu = u, tv = v;
    for(int det = hv-hu, i=0; det; det>>=1, ++i) {
        if(det&1) {
            tv = fa[tv][i];
        }
    }
    if(tu == tv) return tu;
    for(int i = DEG-1; i >= 0; --i) {
        if(fa[tu][i] == fa[tv][i]) continue;    
        tu = fa[tu][i]; 
        tv = fa[tv][i];
    }
    return fa[tu][0];
}
/*****makedis**********/
void solve(int x) {
    memset(vis,0,sizeof(vis));
    queue<int> qq;
    qq.push(x); dis[cc][x] = 0; vis[x] = 1; pre[x]=x;
    while(!qq.empty()) {
        int b = qq.front(); qq.pop();
        for(int i = mp[b]; i != -1; i = mip[i].nex) {
            int y = mip[i].to;
            if(!vis[y]) {
        //      if(!cc) printf("hh %d %d\n",b,y);
                dis[cc][y] = dis[cc][b]+1; vis[y] = 1; pre[y]=b;
                if(!cc) {
                    add2(b,y);
                }
                qq.push(y);
            }else if(pre[b] != y && !cc) {
        //      printf("%d %d\n",b,y);
                tag[b]++; if(tag[b] == 1) po[++po_cc] = b;
                tag[y]++; if(tag[y] == 1) po[++po_cc] = y;
            }
        }
    }
}
int doo(int x,int y) {
    int tt = LCA(x,y);
    int ans = -dis[0][tt]*2 + dis[0][x] + dis[0][y];
    if(tt == x || tt == y) return ans;
    for(int i = 1; i <= po_cc; ++i) {
        ans = min(ans, dis[i][x]+dis[i][y]);
    } 
    return ans;
}
int main(){
    while(~scanf("%d %d %d",&N,&M,&Q)) {
        memset(mp,-1,sizeof(mp)); mot = 0;
        memset(vc,-1,sizeof(vc)); vot = 0;
        memset(tag,0,sizeof(tag));
        mmp.clear(); po_cc = 0; cc = 0;
        for(int i = 1; i <= M; ++i) {
            int a,b; scanf("%d %d",&a,&b);
            if(a > b) swap(a,b);
            if( a == b || mmp[pi(a,b)] ) continue;
            add1(a,b);
            mmp[pi(a,b)] ++;
        }

        solve(1);
        BFS(1); 
        for(int i = 1; i <= po_cc; ++i) {
            cc++; solve(po[i]);
        }
        for(int i = 0; i < Q; ++i) {
            int a,b; scanf("%d %d",&a,&b);
            printf("%d\n",doo(a,b));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值