ZOJ Problem Set - 3422 Go Deeper
Chieh
posted @ 2015年1月05日 11:44
in ZOJ
, 327 阅读
飞机票: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4106
今天起来一道2-sat。。。巩固知识~~~
分析:题目的意思就是说求函数最大能递归到第几层。。。告诉你a,b,c数组。。。x数组未知。。。题目秒懂。。。那个程序就不解释了,ACMer肯定能够看得懂:).这种题该怎么搞??其实这里发现一个限制递归的地方就是
if dep < m and x[a[dep]] + x[b[dep]] != c[dep] then go(dep + 1, n, m)
那个<m就不用讲了。。如果>=m就溢出a,b,c数组了。。。那么其实就是后面的那个条件。。。我们二分0~(m-1)。假设当前的值是mid。。。那么就可以加边了。。。循环从0~mid。。。取出a[k]和b[k],c[k]的值(语文有限。。。望看懂~)那么如果c[k]的值是0.那么x[a[k]]+x[b[k]]的值至少有一个是1 如果是c[k]是1 那么两个值必须相同。。。如果是2 那么两个值肯定不同。。这里发现其实这个跟那个位运算2-sat题型差不多。。。然后把边添加了跑一下tarjan。。。如果不行。。说明递归层太深、、、r=mid-1.如果可以,那么l=mid+1...这样找到最大值即可~啪啪啪。。。TLE(vector忘记清0了。。。bug啊!!!)最后只要把深度+1就可以AC了
/* Author:Chieh Grow up happy */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <stack> #include <vector> #define LL long long using namespace std; const int maxn=456; const int Maxn=12345; struct he { int a,b,c; } JLJ[Maxn]; vector<int> V[maxn]; int n,m; void init() { scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d%d",&JLJ[i].a,&JLJ[i].b,&JLJ[i].c); } } bool instack[maxn]; int dfn[maxn],low[maxn],sta[maxn],belong[maxn],indexx,scnt,cntnum; void tarjan(int u) { dfn[u]=low[u]=indexx++; instack[u]=1; sta[++scnt]=u; for(int i=0; i<V[u].size(); i++) { int v=V[u][i]; if(dfn[v]==-1) { tarjan(v); low[u]=min(low[u],low[v]); } else if(instack[v])low[u]=min(dfn[v],low[u]); } if(dfn[u]==low[u]) { for(int v=-1; v!=u; scnt--) { v=sta[scnt]; instack[v]=0; belong[v]=cntnum; } cntnum++; } } void play() { int l=0; int r=m-1; int over=0; while(l<=r) { int mid=(l+r)/2; for(int i=0;i<=2*n;i++)V[i].clear(); for(int i=0; i<=mid; i++) { int u=JLJ[i].a*2; int v=JLJ[i].b*2; int t=JLJ[i].c; if(t==2) { V[u].push_back(v^1); V[v].push_back(u^1); } else if(t==1) { V[u].push_back(v); V[v].push_back(u); V[u^1].push_back(v^1); V[v^1].push_back(u^1); } else { V[u^1].push_back(v); V[v^1].push_back(u); } } indexx=cntnum=0; scnt=-1; memset(dfn,-1,sizeof(dfn)); memset(instack,0,sizeof(instack)); for(int i=0; i<2*n; i++) { if(dfn[i]==-1)tarjan(i); } bool flag=1; for(int i=0; i<n; i++) { if(belong[i*2]==belong[i*2+1]) { flag=0; break; } } if(!flag) { r=mid-1; continue; } over=max(over,mid); l=mid+1; } printf("%d\n",over+1); } int T; int main() { scanf("%d",&T); while(T--) { init(); play(); } // cout << "Hello world!" << endl; return 0; }