poj 2983

来源:互联网 发布:证券从业资格题库软件 编辑:程序博客网 时间:2024/06/06 09:16

题意:给你n个串,让你找到一系列串,这些串首尾相连(开头和结尾的两个字母相同),问最大的平均长度是多少

思路:做差分约束做到的这道题,但是很明显不是差分约束。。看起来有点像01分数规划=。=,事实证明还是有点关系的。。

///渣渣题解。。不知道的最好出门左转=。=

这道题要求一些字符串长度和的最大值,二分这个最大值,就得到一个不等式,就是 选取的字符串的长度和/n > mid,如果存在这样的串l = mid,反之。。,就这样二分,满足精度 跳出输出解,现在任务就是判断是否存在这样的环,把这个不等式变形之后:长度和>mid * n,接着变形,得到:长度减去mid的和>0,这样把边权换为减去mid的之后,判断是否有正环就好了。。

原来判负环一直都是用spfa判断进队次数,这次学了个dfs版的spfa,传说中比那个快=。=

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#include<vector>#include<queue>const int maxn = 1000;const double eps = 1e-6;int n;struct Side{    int v,next;    double w;}side[maxn*maxn];int node[maxn],top;void add_side(int u,int v,double w){    side[top] = (Side){v,node[u],w};    node[u] = top++;}int mm[maxn][maxn];bool have[maxn];double dis[maxn];bool is[maxn];int flag;///fu huanvoid dfs(int s,double mid){    is[s] = 1;    for(int i = node[s];i != -1;i = side[i].next){        int v = side[i].v;        if(dis[v] < dis[s] + side[i].w - mid){            dis[v] = dis[s] + side[i].w -mid;            if(is[v]){                flag = 1;                return;            }            dfs(v,mid);            if(flag)return;        }    }    is[s] = 0;}bool judge(double mid){    for(int i = 0;i < maxn;i ++){        dis[i] = -10000;        is[i] = false;    }    flag = 0;    for(int i = 1;i < maxn;i ++){        if(have[i]){            dfs(i,mid);            if(flag)return true;        }    }    return false;}int main(){    //freopen("in.txt","r",stdin);    while(~scanf("%d",&n),n){        memset(node,-1,sizeof(node));        memset(mm,0,sizeof(mm));        memset(have,0,sizeof(have));        top = 0;        char s[1100];        double l = 0,r = 0,mid;        for(int i = 1;i <= n;i ++){            scanf("%s",s);            int l = strlen(s);            r = max(r,(double)l);            int tail,head;            if(l == 1)head = tail = s[0] - 'a';            else {                head = (s[0] - 'a')*30 + s[1] - 'a' + 1;                tail = (s[l-2] - 'a')*30 + s[l-1] - 'a' + 1;            }            mm[head][tail] = max(l,mm[head][tail]);            have[head] = have[tail] = 1;        }        for(int i = 0;i < maxn;i ++){            if(have[i] == 0)continue;            for(int j = 0;j < maxn;j ++){                if(have[j] == 0||mm[i][j] == 0)continue;                add_side(i,j,mm[i][j] * 1.0);                //cout<<i<<' '<<j<<' '<<mm[i][j]<<endl;            }        }        while(r - l > eps){            mid = (l + r)/2.0;//cout<<mid<<endl;            if(judge(mid))l = mid;            else r = mid;        }        if(mid < 1.0)printf("No solution.\n");        else printf("%.2f\n",mid);    }    return 0;}


0 0