[POI2012]Festival
2018-01-07 20:03
253 查看
题目大意:
有$n$个正整数$x_1,x_2,\ldots,x_n$,再给出一些限制条件,限制条件分为两类:
1.给出$A,B$,要求满足$X_A+1=X_B$;
2.给出$C,D$,要求满足$X_C\leq X_D$。
其中第1类限制条件有$m_1$个,第2类限制条件有$m_2$个。
问这些限制条件是否能都被满足,如果能,求集合$\{x_i\}$大小的最大值。
思路:
不难想到这是一个差分约束模型。
对于第1类限制,连一条权值为$1$的边$A\to B$,和一条权值为$-1$的边$B\to A$。
对于第2类限制,连一条权值为$0$的边$C\to D$。
这种连边方法很经典,难点在于连边以后如何求出集合大小的最大值。
对于同一个SCC,我们只要跑一下最长路就可以唯一确定当前SCC的权值集合大小,因此我们可以先跑一遍Tarjan,然后Floyd求最长路。
考虑不同SCC的关系。
Tarjan缩完点以后就变成了一个DAG,且DAG上的边一定对应第2类限制(不然一定对称,就变成SCC了)。
我们不妨假设不同SCC中的权值互不重叠,那么我们只需要将所有SCC的答案加起来即可。
#include<stack> #include<cstdio> #include<cctype> #include<vector> #include<algorithm> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int inf=0x7fffffff; const int N=601; struct Edge { int to,w; }; bool ins ; std::stack<int> s; std::vector<Edge> e ; int dis ,low ,dfn ,scc ; inline void add_edge(const int &u,const int &v,const int &w) { e[u].push_back((Edge){v,w}); } void tarjan(const int &x) { low[x]=dfn[x]=++dfn[0]; s.push(x); ins[x]=true; for(unsigned i=0;i<e[x].size();i++) { const int &y=e[x][i].to; if(!dfn[y]) { tarjan(y); low[x]=std::min(low[x],low[y]); } else if(ins[y]) { low[x]=std::min(low[x],dfn[y]); } } if(low[x]==dfn[x]) { scc[0]++; int y=0; while(y!=x) { ins[y=s.top()]=false; s.pop(); scc[y]=scc[0]; } } } int main() { const int n=getint(),m1=getint(),m2=getint(); for(register int i=1;i<=n;i++) { for(register int j=1;j<=n;j++) { if(i!=j) { dis[i][j]=-inf; } } } for(register int i=0;i<m1;i++) { const int u=getint(),v=getint(); add_edge(u,v,1); add_edge(v,u,-1); dis[u][v]=std::max(dis[u][v],1); dis[v][u]=std::max(dis[v][u],-1); } for(register int i=0;i<m2;i++) { const int u=getint(),v=getint(); add_edge(u,v,0); dis[u][v]=std::max(dis[u][v],0); } for(register int i=1;i<=n;i++) { if(!dfn[i]) { tarjan(i); } } int ans=0; for(register int c=1;c<=scc[0];c++) { for(register int k=1;k<=n;k++) { if(scc[k]!=c) continue; for(register int i=1;i<=n;i++) { if(scc[i]!=c||dis[i][k]==-inf) continue; for(register int j=1;j<=n;j++) { if(scc[j]!=c||dis[k][j]==-inf) continue; dis[i][j]=std::max(dis[i][j],dis[i][k]+dis[k][j]); } } } int tmp=0; for(register int i=1;i<=n;i++) { if(scc[i]!=c) continue; for(register int j=1;j<=n;j++) { if(scc[j]!=c) continue; tmp=std::max(tmp,std::abs(dis[i][j])); } } ans+=tmp+1; } for(register int i=1;i<=n;i++) { if(dis[i][i]) { puts("NIE"); return 0; } } printf("%d\n",ans); return 0; }
相关文章推荐
- bzoj 2788: [Poi2012]Festival (差分约束+最短路+tarjan)
- [BZOJ2788]-[Poi2012]Festival-差分约束+tarjan+floyd
- [BZOJ2788][Poi2012]Festival(差分约束+floyed+tarjan)
- BZOJ2788: [Poi2012]Festival
- bzoj 2788 [Poi2012]Festival 差分约束+tarjan+floyd
- BZOJ 2788: [Poi2012]Festival
- bzoj2788 [Poi2012]Festival(差分约束+floyd+tarjan缩点)
- [Poi2012]Festival
- BZOJ 2788 Poi2012 Festival 差分约束+Tarjan+Floyd
- 差分约束+tarjin [Poi2012]Festival
- BZOJ 2788 [Poi2012]Festival 差分约束+tarjan+floyd
- [BZOJ2788][Poi2012]Festival
- BZOJ_2788_[Poi2012]Festival_差分约束+tarjan+floyed
- BZOJ2788: [Poi2012]Festival 差分约束
- [Poi2012]Festival 差分约束+tarjan
- [Poi2012] bzoj 2788 Festival
- [Poi2012]Festival 差分约束+tarjan
- [BZOJ2797][Poi2012]Squarks
- 2802: [Poi2012]Warehouse Store 贪心 priority_queue
- BZOJ2803: [Poi2012]Prefixuffix