zoukankan      html  css  js  c++  java
  • #差分约束,Floyd#洛谷 2474 [SCOI2008]天平

    题目


    分析

    非传统差分约束??
    注意只有结果保证惟一的选法才统计在内
    这就为差分约束提供了依据
    以左边重为例,假设现在选择的砝码为(i,j)
    那么(ecause A+B>i+j herefore A-i>j-B)
    既然结果保证唯一,那么也就是(min(A-i)>max(j-B))
    右边重同理,也就是(max(A-i)<min(j-B))
    同样重也很显然,就是
    (min(A-i)=max(A-i),min(j-B)=max(j-B),max(A-i)=min(j-B))
    讲到这里该怎么做,floyd现身了,考虑维护最短路和最长路,

    1. 等号也就是(i-jleq 0,i-jgeq 0)
    2. 大于号也就是(i-jleq -1,i-jgeq -2)
    3. 小于号也就是(i-jleq 2,i-jgeq 1)
    4. 问号也就是(i-jgeq -2,i-jleq 2)

    按照这个floyd建图分别跑最短路和最长路即可
    这和传统的SPFA有什么区别呢,可以发现它求的是多源最短路,
    那么Floyd要比SPFA更加方便


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=51; char s[N];
    int n,A,B,dmn[N][N],dmx[N][N],ans1,ans2,ans3;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline signed max(int a,int b){return a>b?a:b;}
    signed main(){
    	scanf("%d%d%d",&n,&A,&B);
    	for (rr int i=1;i<=n;++i){
    	    scanf("%s",s+1),s[i]='=';
    	    for (rr int j=1;j<=n;++j)
    	    switch (s[j]){
    	    	case '=':{
    	    		dmn[i][j]=0,dmx[i][j]=0;
    				break;
    			}
    			case '+':{
    				dmn[i][j]=1,dmx[i][j]=2;
    				break;
    			}
    			case '-':{
    				dmn[i][j]=-2,dmx[i][j]=-1;
    				break;
    			}
    			case '?':{
    				dmn[i][j]=-2,dmx[i][j]=2;
    				break;
    			}
    		}
    	}
    	for (rr int k=1;k<=n;++k)
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=1;j<=n;++j)
    	if ((i^k)&&(i^j)&&(k^j))
    		dmn[i][j]=max(dmn[i][j],dmn[i][k]+dmn[k][j]),//下界
    		    dmx[i][j]=min(dmx[i][j],dmx[i][k]+dmx[k][j]);//上界
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=1;j<i;++j)
    	if ((i^j)&&(i^A)&&(i^B)&&(j^A)&&(j^B)){
    		if (dmn[A][i]>dmx[j][B]||dmn[B][i]>dmx[j][A]) ++ans1;
    		if (dmn[i][A]>dmx[B][j]||dmn[i][B]>dmx[A][j]) ++ans3;
    		if ((dmn[A][i]==dmx[A][i]&&dmn[j][B]==dmx[j][B]&&dmn[A][i]==dmx[j][B])||
    		    (dmn[A][j]==dmx[A][j]&&dmn[i][B]==dmx[i][B]&&dmn[A][j]==dmx[i][B]))
    		    ++ans2;
    	}
    	return !printf("%d %d %d",ans1,ans2,ans3);
    } 
    
  • 相关阅读:
    关于form表单的相同name问题
    MySQL数据库视图
    Blazor
    查看Oracle正在执行的任务
    比较不错的几款开源的WPF Charts报表控件
    Raft算法
    EntityFramework 使用Linq处理内连接(inner join)、外链接(left/right outer join)、多表查询
    systemd、upstart和system V 枯木
    MRTG生成首页报错解决方法 枯木
    dd备份和恢复 枯木
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13928622.html
Copyright © 2011-2022 走看看