ACM-ICPC wf2014 金属加工厂 metal 单调性维护+2_SAT
来源:互联网 发布:网络与internet连不上 编辑:程序博客网 时间:2024/04/29 17:20
【问题描述】
定义集合S的价值D(S)为:
现在给你n个元素,并给出其中任意两个元素之间的d(i,j)值,要你将这些元素划分成两个集合A、B。求min{D(A)+D(B)}。注:d(i,j)=d(j,i)。
【输入格式】
输入数据的第一行是一个整数n,代表元素个数。
之后n-1行描述的是d(i,j),这部分里,第i行包含n-i个整数,第i行第j列的整数代表的是d(i,i+j)。
【输出格式】
输出只有一行,一个整数,代表min{D(A)+D(B)}。
【输入样例】
【样例1】
5
4 5 0 2
1 3 7
2 0
4
【样例2】
7
1 10 5 5 5 5
5 10 5 5 5
100 100 5 5
10 5 5
98 99
3
【输出样例】
【样例1】
4
【样例2】
15
【数据范围】
1 ≤ n ≤ 200
0<=d(i,i+j)<=10^9
——————————————————————————————————————————————————————
想到可以用2_SAT来判定,但是这是判定,关键是主程序的框架怎么写。
肯定要先把所有的边拿出来排序搞事情这个没话说的。
想了很久二分套二分,发现一点道理都没有。。。。
后来又想枚举一边二分另一边,嗯似乎很有道理的样子,但是仔细一想不对要TL。。。。(我家题库上时限1S简直。。QAQ)
已经发现可以枚举一边二分另一边了,那么就考虑一下维护两个单调指针。这个指针代表的是当前情况下两个集合中各自最大的边的权值。然后在2_SAT中把一个点拆成2个分别表示在第一个集合(一下简称0)和在第二个集合(以下简称1)的情况,然后就开始考虑建立2 _SAT的判定图。(可以证明这是满足单调性的,但是有一点复杂,主要是考虑一些特殊情况以及假设验证,同时2 _SAT判定到假解的影响是会被消除的,证了两节晚自习。。。)
左指针(以下简称L)右边的所有边连接的点都要连边0->1,右指针(以下简称R)右边的边连接的点都要连边1->0,然后在左右指针向右向左走的过程中就会出现L经过的地方删边,R经过的地方要加边,所以要动态维护(打标记会TL的很惨ORZ)。
但是这样还是会TL,要加一个剪枝,发现加的边连接的点在上一次判定成功的图中全都在不同集合中的时候就可以不用重新判定了。
然后就可以1S过了。
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<vector>#include<cctype>#define inf 2*1e9+5using namespace std;const int maxn=205;const int maxm=40005;int N,g[maxn][maxn];int ans=inf;bool vis[maxn<<1];struct _edge{ int from,to,w; }_E[maxm];struct edge{ int to,next; }E[maxm<<1];int first[maxn<<1],np,cnt,other[maxn<<1];int stk[maxn<<1],top;void data_in(){ scanf("%d",&N); int x; for(int i=1;i<N;i++) for(int j=i+1;j<=N;j++) { scanf("%d",&x); g[i][j]=g[j][i]=x; }}bool cmp(_edge x,_edge y) { return x.w<y.w; }void add_edge(int u,int v){ E[++np]=(edge){v,first[u]}; first[u]=np;}void delete_edge(int u,int v){ int p=first[u],lastp=0; while(p) { if(E[p].to==v) break; lastp=p; p=E[p].next; } if(lastp) E[lastp].next=E[p].next; else first[u]=E[p].next;}void init(){ for(int i=1;i<N;i++) for(int j=i+1;j<=N;j++) _E[++cnt]=(_edge){i,j,g[i][j]}; sort(_E+1,_E+cnt+1,cmp); for(int i=1;i<=N;i++) other[i]=i+N,other[i+N]=i; for(int i=1;i<=cnt;i++) { int x=_E[i].from,y=_E[i].to; add_edge(x,other[y]); add_edge(y,other[x]); }}bool DFS(int i){ vis[i]=1; stk[++top]=i; for(int p=first[i];p;p=E[p].next) { int j=E[p].to; if(vis[j]) continue; if(vis[other[j]]) return 0; if(!DFS(j)) return 0; } return 1;}bool two_SAT(){ memset(vis,0,sizeof(vis)); for(int i=1;i<=N;i++) if(!vis[i]&&!vis[other[i]]) { top=0; if(!DFS(i)) { while(top) vis[stk[top--]]=0; if(!DFS(other[i])) return 0; } } return 1;}void work100(){ init(); int L=0,R=cnt; bool ok=0; while(L<=R) { if(ok||two_SAT()) { ok=1; ans=min(ans,_E[L].w+_E[R].w); add_edge(other[_E[R].from],_E[R].to); add_edge(other[_E[R].to],_E[R].from); if(!(vis[_E[R].from]&&vis[other[_E[R].to]] ||vis[_E[R].to]&&vis[other[_E[R].from]])) ok=0; R--; while(R>L&&_E[R].w==_E[R+1].w) { add_edge(other[_E[R].from],_E[R].to); add_edge(other[_E[R].to],_E[R].from); if(!(vis[_E[R].from]&&vis[other[_E[R].to]] ||vis[_E[R].to]&&vis[other[_E[R].from]])) ok=0; R--; } } else { ok=0; L++; delete_edge(_E[L].from,other[_E[L].to]); delete_edge(_E[L].to,other[_E[L].from]); while(L<R&&_E[L].w==_E[L+1].w) { L++; delete_edge(_E[L].from,other[_E[L].to]); delete_edge(_E[L].to,other[_E[L].from]); } } } if(N==1||N==2) ans=0; printf("%d\n",ans);}int main(){ freopen("test.in","r",stdin); freopen("test.out","w",stdout); data_in(); work100(); return 0;}
- ACM-ICPC wf2014 金属加工厂 metal 单调性维护+2_SAT
- [Wf2014]Metal Processing Plant(金属加工厂) 之这是小少主我用二分答案用得最6的一次(所有数据共1S)
- bzoj 4078 [Wf2014]Metal Processing Plant 2SAT 二分图
- ACM-ICPC Live Archive 6505---Metal(二分)
- 【BZOJ4078】[Wf2014]Metal Processing Plant【2-SAT】【二分】【二分图】【并查集】
- 2_SAT问题
- HDU 3622 2_SAT
- POJ 3207 2_sat
- 2_SAT问题小结
- Cg Programming/Unity/Brushed Metal拉丝金属
- hdu4282(单调性+二分)
- hdu2428(单调性+二分)
- BZOJ2216【决策单调性】
- 单调性与周期性
- poj 3648 Wedding 2_SAT
- hnoi2010 平面图判定 2_SAT
- ICPC-ACM
- ACM/ICPC
- leveldb存储引擎分析
- JVM:类的加载时机与加载过程
- 自定义动画
- 欢迎使用CSDN-markdown编辑器
- 【Node网络模块NET】
- ACM-ICPC wf2014 金属加工厂 metal 单调性维护+2_SAT
- 教育投入我二姨
- 对imageLoader进行配置
- Android Studio如何修改快捷键
- JavaScript的递归函数
- VS项目属性的一些总结
- JS排序算法
- 进程
- 算法竞赛入门经典(第二版)第二章课后习题