BZOJ1077 天平
来源:互联网 发布:中国高铁在欧洲 知乎 编辑:程序博客网 时间:2024/04/28 13:02
本题不好下手 , 所以提示一下 , 大家就可以不用看我代码下的分析了 , 这样对训练思维大有裨益。
提示:
1. 相互等于的量其实没有必要分开讨论 , 因为她们任何时候都是一个整体
2. 如果两个量本身就不联通 , 那么的约束关系就很弱。 比如
3. 现在我们要统计个数 , 因为数据很小 , 完全可以枚举另外两个是什么 , 然后在看看她们是否与A和B的关系是确定的就OK了。
详细说明见代码后:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <algorithm>#define FOR(va , a) for(int va=l[fa[a]];va<=r[fa[a]];va++)using namespace std;const int maxn = 55;int n , A , B;char s[maxn][maxn];int fa[maxn];int getfa(int a) { return fa[a]==a?a:(fa[a] = getfa(fa[a])); }void link(int a , int b){ if(getfa(a)==getfa(b)) return; fa[getfa(a)] = getfa(b);}int v[maxn];int g[maxn][maxn];int l[maxn] , r[maxn];int cmp(int a) { return a==0?a:(a>0?1:-1); }int main(int argc, char *argv[]) { scanf("%d%d%d" , &n , &A , &B); A--; B--; for(int i=0;i<n;i++) scanf("%s" , s[i]) , fa[i] = i; for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(s[i][j]=='=') link(i, j); for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(s[i][j]=='+') g[getfa(i)][getfa(j)] = 1 , g[getfa(j)][getfa(i)] = -1; else if(s[i][j]=='-') g[getfa(i)][getfa(j)] = -1 , g[getfa(j)][getfa(i)] = 1; vector<int> rep; for(int i=0;i<n;i++) if(getfa(i)==i) rep.push_back(i); for(int i=0;i<rep.size();i++) { int b = 0 , s = 0; for(int j=0;j<rep.size();j++) b|= (g[rep[i]][rep[j]]==1) , s|= (g[rep[i]][rep[j]]==-1); if(!b || !s) continue; v[rep[i]] = 2; for(int j=0;j<rep.size();j++) if(g[rep[i]][rep[j]]==1) v[rep[j]] = 1; else if(g[rep[i]][rep[j]]==-1) v[rep[j]] = 3; } for(int i=0;i<rep.size();i++) { int u = rep[i]; l[u] = 1; r[u] = 3; if(v[u]) l[u] = r[u] = v[u]; else { for(int j=0;j<rep.size();j++) if(g[u][rep[j]]==1) l[u] = 2; else if(g[u][rep[j]]==-1) r[u] = 2; } } int r1 = 0 , r2 = 0 , r3 = 0; for(int i=0;i<n;i++) if(i!=A && i!=B) for(int j=i+1;j<n;j++) if(j!=A && j!=B) { int p1 = 0 , p2 = 0 ,p3 = 0; FOR(va, A) FOR(vb, B) FOR(vi, i) FOR(vj, j) { int relat[]={fa[A] , fa[B] , fa[i] , fa[j]}; int relav[]={va , vb , vi , vj}; bool ok = true; for(int t1=0;t1<4;t1++) for(int t2=t1+1;t2<4;t2++) if(relat[t1]==relat[t2] && relav[t1]!=relav[t2]) { ok = false; t1 = 4; break; } else if(g[relat[t1]][relat[t2]] && g[relat[t1]][relat[t2]] != cmp(relav[t1]-relav[t2])) { ok = false; t1 = 4; break; } if(!ok) continue; if(va+vb==vi+vj) p2 = 1; if(va+vb <vi+vj) p3 = 1; if(va+vb >vi+vj) p1 = 1; } if(p1+p2+p3==1) r1+=p1 , r2+=p2 , r3+=p3; } printf("%d %d %d\n" , r1 , r2 , r3); return 0;}
详解:
1. 把相等的作为一个整体 , 每次都以并查集的祖先编号来访问。
2. 值不相等的进行连边 , 如果一个点既有前驱也有后继 , 那么这个点为2 , 更新所有与他相关的点的值。
3. 计算每个值相等的块的可能值 , 便于以后的枚举。
4. 枚举天平右端的两个数 , 并且枚举这四个数的值 , 看是否合法。
注意: 每个数的可能取值要考虑到他是否有前驱和后继 , 代码中步骤写的很详细
0 0
- BZOJ1077 天平
- BZOJ1077: [SCOI2008]天平
- bzoj1077: [SCOI2008]天平
- 【BZOJ1077】【SCOI2008】天平
- [BZOJ1077][SCOI2008]天平(差分约束)
- 天平
- bzoj1077 -- 并查集
- 天平感悟
- 天平问题
- 天平称重
- 天平问题
- 天平称量
- B. 天平
- 天平难题
- Uva839-天平
- jzoj1252. 天平
- 1252. 天平
- HDU1709 天平
- [总结]PHP字符串处理
- 告诉你自己一定要努力
- 手势解锁-九宫格
- 虚拟机下安装UEFI+GPT+win7x64
- svn-eclipse插件的安装
- BZOJ1077 天平
- ubuntu(linux)下source、sh/bash、./ 和 直接 执行脚本的区别
- CSS实现文字随屏幕变化
- jquery animate扩展
- 298. Binary Tree Longest Consecutive Sequence
- Hdu1241Oil Deposits
- 最全常用正则表达式列表
- 对View绘制流程的一些理解
- Codeforces Round #340 (Div. 2)-A. Elephant(贪心)