BZOJ 3143 HNOI2013 游走

Problem

BZOJ

Solution

用p(x)表示点x被走的概率,d(x)表示点x的度
那么一条边(x,y)被走的概率就是 p(x)d(x)+p(y)d(y) p ( x ) d ( x ) + p ( y ) d ( y )
那么我们考虑算点的概率p,然而这可能会产生一个环,所以我们考虑用高斯消元
最后贪心按照概率给边赋值。

但这道题很毒瘤,eps至少要设置到1e-10,不然会WA

Code

#include 
#include 
using namespace std;
const int maxn=250010;
const double eps=1e-10;
int n,m,p,s[maxn],t[maxn],head[510];
double ans,a[510][510],in[510],ex[maxn],anss[510];
struct data{int v,nxt;}edge[maxn<<1];
inline double fabs(double x){return x<0?-x:x;}
inline void insert(int u,int v)
{
    edge[++p]=(data){v,head[u]};head[u]=p;
    edge[++p]=(data){u,head[v]};head[v]=p;
}
int dcmp(double x)
{
    if (x<=eps&&x>=-eps) return 0;
    return (x>0)?1:-1;
}
void gauss()
{
    for (int i=1;iint num=i;
        for (int j=i+1;jif (dcmp(a[j][i]-a[num][i])>0) num=j;
        if (num!=i)
            for (int j=1;j1;j++)
                swap(a[i][j],a[num][j]);
        for (int j=i+1;jif (dcmp(a[j][i]))
            {
                double t=a[j][i]/a[i][i];
                for (int k=1;k1;k++)
                    a[j][k]-=t*a[i][k];
            }
    }
    for (int i=n-1;i>=1;i--)
    {
        for (int j=i+1;jint main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        insert(x,y);in[x]+=1.0;in[y]+=1.0;
        s[i]=x;t[i]=y;
    }
    for(int i=1;i1.0;
        for(int j=head[i];j;j=edge[j].nxt)
          if(edge[j].v!=n)
            a[i][edge[j].v]=-1.0/in[edge[j].v];
    }
    a[1][n]=1.0;
    gauss();
    for(int i=1;i<=m;i++) ex[i]=anss[s[i]]/in[s[i]]+anss[t[i]]/in[t[i]];
    sort(ex+1,ex+m+1);
    for(int i=1;i<=m;i++) ans+=ex[i]*(m-i+1.0);
    printf("%.3lf\n",ans);
    return 0;
}

你可能感兴趣的:(HNOI,BZOJ)