BZOJ4643 卡常大水题 【Tarjan】

题目分析:

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

代码:

#include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int maxm = ; 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=;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 = ;
for(int i=;i<=n;i++) low[i] = dfn[i] = ;
Tarjan();
for(int i=;i<=n;i++) if(low[i] == dfn[i]) return ;
return ;
} void read(){
scanf("%d",&n);
for(int i=;i<=n;i++) for(int j=;j<=n;j++){
int x; scanf("%d",&x);
edges[n*(i-)+j]=(edge){i,j,x,};
}
for(int i=;i<=n;i++) for(int j=;j<=n;j++) {
int x; scanf("%d",&x);
edges[n*(i-)+j].w2 = x;
}
sort(edges+,edges+n*n+,cmp);
} void work(){
int ans = 2e9;
int flag = ,lstans = ;
for(int i=;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 = ;
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=;i<g[u].size();i++){
if(g[u][i] == v){
swap(g[u][i],g[u][g[u].size()-]);
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 ;
}
上一篇:小tip:CSS计数器+伪类实现数值动态计算与呈现【转】


下一篇:Android手机指令操作释疑