BZOJ4643 卡常大水题 【Tarjan】

题目分析:

给所有边按A排序,依次加入再按B递增排序,势能分析可以发现是O(n^4)的

代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 156;
const int maxm = 22540;

int n,cl,dfn[maxn],low[maxn];
struct edge{int u,v,w1,w2;}edges[maxm];
vector <int> g[maxn];
int cmp(edge alpha,edge beta){return alpha.w1 < beta.w1;}

set<pair<int,pair<int,int> > > st;

void Tarjan(int now){
    low[now] = dfn[now] = ++cl;
    for(int i=0;i<g[now].size();i++){
        int t = g[now][i];
        if(dfn[t]) low[now] = min(low[now],dfn[t]);
        else{Tarjan(t); low[now] = min(low[now],low[t]);}
    }
}

int chk(){// to check if it is Strong Connect Graph
    cl = 0;
    for(int i=1;i<=n;i++) low[i] = dfn[i] = 0;
    Tarjan(1);
    for(int i=2;i<=n;i++) if(low[i] == dfn[i]) return 0;
    return 1;
}

void read(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
            int x; scanf("%d",&x);
            edges[n*(i-1)+j]=(edge){i,j,x,0};
        }
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) {
            int x; scanf("%d",&x);
            edges[n*(i-1)+j].w2 = x;    
        }
    sort(edges+1,edges+n*n+1,cmp);
}

void work(){
    int ans = 2e9;
    int flag = 0,lstans = 0;
    for(int i=1;i<=n*n;i++){
        if(edges[i].u == edges[i].v) continue;
        int bb = edges[i].w1;
        if(flag&&lstans < edges[i].w2) continue;
        st.insert(make_pair(edges[i].w2,make_pair(edges[i].u,edges[i].v)));
        g[edges[i].u].push_back(edges[i].v);
        if(!flag){
            if(chk()){
                set<pair<int,pair<int,int> > >::iterator it = st.end();
                it--;
                lstans = (*it).first;
                flag = 1;
                ans = min(ans,lstans+bb);
            }
            continue;
        }
        while(true){
            set<pair<int,pair<int,int> > >::iterator it = st.end();
            it--;int u = (*it).second.first,v = (*it).second.second;
            for(int i=0;i<g[u].size();i++){
                if(g[u][i] == v){
                    swap(g[u][i],g[u][g[u].size()-1]);
                    g[u].pop_back();
                    break;
                }
            }    
            if(chk()){
                st.erase(it);
            }else {g[u].push_back(v);break;}
        }
        set<pair<int,pair<int,int> > >::iterator it = st.end();
        it--;lstans = (*it).first;
        ans = min(ans,(*it).first+bb);
    }
    printf("%d\n",ans);
}

int main(){
    read();
    work();
    return 0;
}

 

posted @ 2019-01-19 15:34  menhera  阅读(253)  评论(0编辑  收藏  举报