码迷,mamicode.com
首页 > 其他好文 > 详细

[kuangbin带你飞]专题六 生成树

时间:2015-09-11 20:44:34      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:

A. POJ 1679  The Unique MST

题意:最小生成树是不是唯一的。

思路:参考http://www.cnblogs.com/onlyAzha/p/4793031.html

B. HDU 4081  Qin Shi Huang‘s National Road System

题意:秦始皇想要在城市之间修路。徐福可以用法力帮助他修一条路。秦始皇希望修一条路使得剩下的路需要的花费B最少,而徐福希望这条路所连的两个城市的人口数之和A最大。权衡后他们决定选择A/B的值最大的边来修建。

思路:可以想到A/B的最大值必然是在最小生成树上,或者在最小生成树上加入一条边,然后删去形成的环中最长的那条边。用求次小生成树的方法,求出MAX[i][j],即i,j两点路径上A/B的最大值。然后再枚举每一条不在最小生成树上的边,加入这条边,然后删去路径上最长的边,求出最大的A/B。

技术分享
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()


using namespace std;

int T,n,m,w,flag;
double ans;
const int MAXN=1100;
const double inf=1e14;

struct v{
    int x,y;
}v[MAXN];

bool vis[MAXN];
double lowc[MAXN];
int pre[MAXN];
int po[MAXN];
double Max[MAXN][MAXN];//Max[i][j]表示在最小生成树中从i到j的路径中的最大边权
bool used[MAXN][MAXN];
double cost[MAXN][MAXN];
double a;

double dist(int i,int j)
{
    return sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x)+(v[i].y-v[j].y)*(v[i].y-v[j].y));
}
double Prim(double cost[][MAXN],int n)
{
    double ans=0;
    memset(vis,false,sizeof(vis));
    memset(Max,0,sizeof(Max));
    memset(used,false,sizeof(used));
    vis[0]=true;
    pre[0]=-1;
    for(int i=1;i<n;i++)
    {
        lowc[i]=cost[0][i];
        pre[i]=0;
    }
    lowc[0]=0;
    for(int i=1;i<n;i++)
    {
        double minc=inf;
        int p=-1;
        for(int j=0;j<n;j++)
            if(!vis[j]&&minc>lowc[j])
            {
                minc=lowc[j];
                p=j;
            }
        if(p==-1)return -1;
        ans+=minc;
        vis[p]=true;
        used[p][pre[p]]=used[pre[p]][p]=true;
        for(int j=0;j<n;j++)
        {
            if(vis[j]&&j!=p)  Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]);
            if(!vis[j]&&lowc[j]>cost[p][j])
            {
                lowc[j]=cost[p][j];
                pre[j]=p;
            }
        }
    }
    return ans;
}

int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        a=0;
        memset(v,0,sizeof(v));
        memset(po,0,sizeof(po));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j)cost[i][j]=0;
                else cost[i][j]=inf;
            }
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&v[i].x,&v[i].y,&po[i]);
            for(int j=0;j<i;j++)
                cost[i][j]=cost[j][i]=dist(i,j);
        }

        ans=Prim(cost,n);

        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(i!=j)
                {
                    if(!used[i][j])
                        a=max((po[i]+po[j])*1.0/(ans-Max[i][j]),a);
                    else
                        a=max((po[i]+po[j])*1.0/(ans-cost[i][j]),a);
                }
        printf("%.2f\n",a);
    }
    return 0;
}
View Code

E. POJ 3164  Command Network

最小树形图。朱刘算法。

技术分享
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<cmath>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()


using namespace std;

const int INF=0x3f3f3f3f;
const int MAXN=110;
const int MAXM=40010;

struct Edge{
    int u,v;
    double cost;
};

struct V{
    int x,y;
}vn[200];

Edge edge[MAXM];

int pre[MAXN],id[MAXN],visit[MAXN];
double in[MAXN];
double zhuliu(int root,int n,int m,Edge edge[])
{
    double res=0;
    int u,v;
    while(1)
    {
        for(int i=0;i<n;i++)
            in[i]=INF*1.0;
        for(int i=0;i<m;i++)
            if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
            {
                pre[edge[i].v]=edge[i].u;
                in[edge[i].v]=edge[i].cost;
            }
        for(int i=0;i<n;i++)
            if(i!=root&&in[i]==INF*1.0)
                return -1;
        int tn=0;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        in[root]=0;
        for(int i=0;i<n;i++)
        {
            res+=in[i];
            v=i;
            while(visit[v]!=i&&id[v]==-1&&v!=root)
            {
                visit[v]=i;
                v=pre[v];
            }
            if(v!=root&&id[v]==-1)
            {
                for(int u=pre[v];u!=v;u=pre[u])
                    id[u]=tn;
                    id[v]=tn++;
            }
        }
        if(tn==0) break;
        for(int i=0;i<n;i++)
            if(id[i]==-1)
                id[i]=tn++;
        for(int i=0;i<m;)
        {
            v=edge[i].v;
            edge[i].u=id[edge[i].u];
            edge[i].v=id[edge[i].v];
            if(edge[i].u!=edge[i].v)
                edge[i++].cost-=in[v];
            else
                swap(edge[i],edge[--m]);
        }
        n=tn;
        root=id[root];
    }
    return res;
}

double g[MAXN][MAXN];

double dist(int i,int j)
{
    return sqrt((vn[i].x-vn[j].x)*(vn[i].x-vn[j].x)*1.0+(vn[i].y-vn[j].y)*(vn[i].y-vn[j].y));
}

int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        memset(vn,0,sizeof(vn));
        memset(g,0,sizeof(g));
        memset(edge,0,sizeof(edge));

        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                g[i][j]=INF;
        int u,v;
        double cost;
        for(int i=0;i<n;i++)
            scanf("%d%d",&vn[i].x,&vn[i].y);
        while(m--)
        {
            scanf("%d%d",&u,&v);
            u--,v--;
            if(u==v) continue;
            cost=dist(u,v);

            g[u][v]=min(g[u][v],cost);
        }
        int L=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(g[i][j]<INF)
                {
                    edge[L].u=i;
                    edge[L].v=j;
                    edge[L++].cost=g[i][j];
                }
        double ans=zhuliu(0,n,L,edge);
        if(ans==-1)
            printf("poor snoopy\n");
        else
            printf("%.2lf\n",ans);
    }
}
View Code

F. UVA 11183  Teen Girl Squad

技术分享
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()


using namespace std;

const int INF=0x3f3f3f3f;
const int MAXN=1010;
const int MAXM=40010;

struct Edge{
    int u,v,cost;
};

Edge edge[MAXM];

int pre[MAXN],id[MAXN],visit[MAXN],in[MAXN];
int zhuliu(int root,int n,int m,Edge edge[])
{
    int res=0,u,v;
    while(1)
    {
        for(int i=0;i<n;i++)
            in[i]=INF;
        for(int i=0;i<m;i++)
            if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
            {
                pre[edge[i].v]=edge[i].u;
                in[edge[i].v]=edge[i].cost;
            }
        for(int i=0;i<n;i++)
            if(i!=root&&in[i]==INF)
                return -1;
        int tn=0;
        memset(id,-1,sizeof(id));
        memset(visit,-1,sizeof(visit));
        in[root]=0;
        for(int i=0;i<n;i++)
        {
            res+=in[i];
            v=i;
            while(visit[v]!=i&&id[v]==-1&&v!=root)
            {
                visit[v]=i;
                v=pre[v];
            }
            if(v!=root&&id[v]==-1)
            {
                for(int u=pre[v];u!=v;u=pre[u])
                    id[u]=tn;
                    id[v]=tn++;
            }
        }
        if(tn==0) break;
        for(int i=0;i<n;i++)
            if(id[i]==-1)
                id[i]=tn++;
        for(int i=0;i<m;)
        {
            v=edge[i].v;
            edge[i].u=id[edge[i].u];
            edge[i].v=id[edge[i].v];
            if(edge[i].u!=edge[i].v)
                edge[i++].cost-=in[v];
            else
                swap(edge[i],edge[--m]);
        }
        n=tn;
        root=id[root];
    }
    return res;
}

int g[MAXN][MAXN];

int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    int iCase=0;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        iCase++;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                g[i][j]=INF;
        int u,v,cost;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&cost);
            if(u==v) continue;
            g[u][v]=min(g[u][v],cost);
        }
        int L=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(g[i][j]<INF)
                {
                    edge[L].u=i;
                    edge[L].v=j;
                    edge[L++].cost=g[i][j];
                }
        int ans=zhuliu(0,n,L,edge);
        printf("Case #%d: ",iCase);
        if(ans==-1)
            printf("Possums!\n");
        else
            printf("%d\n",ans);
    }
}
View Code

G. HDU 2121  Ice_cream‘s World II

技术分享
#include<iostream>  
using namespace std;  
#include<cstdio>  
#include<cstring>  
#define MAXN 1005  
#define INF 0x7f7f7f7f  
typedef __int64 type;  
struct node//边的权和顶点  
{  
    int u, v;  
    type w;  
}edge[MAXN * MAXN];  
int pre[MAXN], id[MAXN], vis[MAXN], n, m, pos;  
type in[MAXN];//存最小入边权,pre[v]为该边的起点  
type Directed_MST(int root, int V, int E)  
{  
    type ret = 0;//存最小树形图总权值  
    while(true)  
    {  
        int i;  
        //1.找每个节点的最小入边  
        for( i = 0; i < V; i++)  
            in[i] = INF;//初始化为无穷大  
        for( i = 0; i < E; i++)//遍历每条边  
        {  
            int u = edge[i].u;  
            int v = edge[i].v;  
            if(edge[i].w < in[v] && u != v)//说明顶点v有条权值较小的入边  记录之  
            {  
                pre[v] = u;//节点u指向v  
                in[v] = edge[i].w;//最小入边  
                if(u == root)//这个点就是实际的起点  
                    pos = i;  
            }  
        }  
        for( i = 0; i < V; i++)//判断是否存在最小树形图  
        {  
            if(i == root)  
                continue;  
            if(in[i] == INF)   
                return -1;//除了根以外有点没有入边,则根无法到达它  说明它是独立的点 一定不能构成树形图  
        }  
        //2.找环  
        int cnt = 0;//记录环数  
        memset(id, -1, sizeof(id));  
        memset(vis, -1, sizeof(vis));  
        in[root] = 0;  
        for( i = 0; i < V; i++) //标记每个环  
        {  
            ret += in[i];//记录权值  
            int v = i;  
            while(vis[v] != i && id[v] == -1 && v != root)  
            {  
                vis[v] = i;  
                v = pre[v];  
            }  
            if(v != root && id[v] == -1)  
            {  
                for(int u = pre[v]; u != v; u = pre[u])  
                    id[u] = cnt;//标记节点u为第几个环  
                id[v] = cnt++;  
            }  
        }  
        if(cnt == 0)  
            break; //无环   则break  
        for( i = 0; i < V; i++)  
            if(id[i] == -1)  
                id[i] = cnt++;  
            //3.建立新图   缩点,重新标记   
            for( i = 0; i < E; i++)  
            {  
                int u = edge[i].u;  
                int v = edge[i].v;  
                edge[i].u = id[u];  
                edge[i].v = id[v];  
                if(id[u] != id[v])  
                    edge[i].w -= in[v];  
            }  
            V = cnt;  
            root = id[root];  
    }  
    return ret;  
}  
int main()  
{  
    int i;  
    while(scanf("%d%d", &n, &m) != EOF)  
    {  
        type sum = 0;  
        for( i = 0; i < m; i++)  
        {  
            scanf("%d%d%I64d", &edge[i].u, &edge[i].v, &edge[i].w);  
            edge[i].u++; edge[i].v++;  
            sum += edge[i].w;  
        }  
      sum ++;  
        for( i = m; i < m + n; i++)//增加超级节点0,节点0到其余各个节点的边权相同(此题中 边权要大于原图的总边权值)  
        {  
            edge[i].u = 0;  
            edge[i].v = i - m + 1;  
            edge[i].w = sum;  
        }  
        type ans = Directed_MST(0, n + 1, m + n);  
        //n+1为总结点数,m+n为总边数  
        //ans代表以超级节点0为根的最小树形图的总权值,  
        //将ans减去sum,如果差值小于sum,说明节点0的出度只有1,说明原图是连通图  
        //如果差值>=sum,那么说明节点0的出度不止为1,说明原图不是连通图  
        if(ans == -1 || ans - sum >= sum)  
            puts("impossible");  
        else  
            printf("%I64d %d\n",ans - sum, pos - m);  
        puts("");  
    }  
    return 0;  
}  
View Code

I. UVA 10766  Organising the Organisation

生成树计数模板

技术分享
#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<algorithm>  
using namespace std;  
  
const int N=55;  
  
typedef long long LL;  
  
int D[N][N];  
LL C[N][N];//Kirchhoff矩阵  
  
LL Det(LL a[][N],int n)//生成树计数:Matrix-Tree定理  
{  
    LL ret=1;  
    for(int i=1; i<n; i++)  
    {  
        for(int j=i+1; j<n; j++)  
            while(a[j][i])  
            {  
                LL t=a[i][i]/a[j][i];  
                for(int k=i; k<n; k++)  
                    a[i][k]=(a[i][k]-a[j][k]*t);  
                for(int k=i; k<n; k++)  
                    swap(a[i][k],a[j][k]);  
                ret=-ret;  
            }  
        if(a[i][i]==0)  
            return 0;  
        ret=ret*a[i][i];  
    }  
    if(ret<0)  
        ret=-ret;  
    return ret;  
}  
  
int main()  
{  
    //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);  
    int n,m,k;  
    while(~scanf("%d%d%d",&n,&m,&k))  
    {  
        memset(C,0,sizeof(C));  
        memset(D,0,sizeof(D));  
        int u,v;  
        while(m--)  
        {  
            scanf("%d%d",&u,&v);  
            u--;  
            v--;  
            D[u][v]=D[v][u]=1;  
        }  
        for(int i=0; i<n; i++)  
        {  
            int u=0;  
            for(int j=0; j<n; j++)  
            {  
                if(i!=j&&!D[i][j])  
                {  
                    u++;  
                    C[i][j]=-1;  
                }  
  
            }  
            C[i][i]=u;  
        }  
        LL res=Det(C,n);  
        printf("%lld\n",res);  
    }  
    return 0;  
}  
View Code

L. HDU 4305  Lightning

技术分享
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()


using namespace std;


const int MOD=10007;
const int MAXN=1000;
const int MAXM=50000;
const double eps=1e-18;


struct Point{
    int x,y;
    Point(int _x=0,int _y=0)
    {
        x=_x;y=_y;
    }
    Point operator - (const Point &b)const
    {
        return Point(x-b.x,y-b.y);
    }
    int operator ^ (const Point &b)const
    {
        return x*b.y-y*b.x;
    }
    void input()
    {
        scanf("%d%d",&x,&y);
    }
};

struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s=_s;e=_e;
    }
};


ll g[MAXN][MAXN];
ll degree[MAXN];
ll a[MAXN][MAXN];
Point p[MAXN];

int T,n,m,u,v;
int R;



bool onSeg(Point P,Line L)
{
    return
    ((L.s-P)^(L.e-P)) == 0 &&
    (P.x-L.s.x)*(P.x-L.e.x)<=0 &&
    (P.y-L.s.y)*(P.y-L.e.y)<=0;
}

int dist(Point a,Point b)
{
    return  (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

bool check(int k1,int k2)
{
    Line(p[k1],p[k2]);
    if(dist(p[k1],p[k2])<=R*R)
    {
        for(int i=0;i<n;i++)
        {
            if(i!=k1&&i!=k2)
                if(onSeg(p[i],Line(p[k1],p[k2])))
                    return 0;
        }
        return 1;
    }
    return 0;
}

int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0)
        return -1;
    else
        return 1;
}

ll inv(ll a,ll b)
{
    if(a==1) return 1;
    return inv(b%a,b)*(b-b/a)%b;
}

ll det(ll a[][MAXN],int n)
{
    ll ret=1;
    int i,j,k;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            a[i][j]=(a[i][j]%MOD+MOD)%MOD;
    for(i=0;i<n;i++)
    {
        if(a[i][i]==0)
        {
            for(j=i+1;j<n;j++)
                if(a[j][i])
                    break;
            if(j==n) return -1;
            for(k=i;k<n;k++)
                swap(a[i][k],a[j][k]);
            ret=(-ret+MOD)%MOD;
        }
        ret=(ret*a[i][i])%MOD;
        ll tp=inv(a[i][i],MOD)%MOD;
        for(k=i+1;k<n;k++)
            a[i][k]=(a[i][k]*tp)%MOD;
        for(j=i+1;j<n;j++)
            for(k=i+1;k<n;k++)
            {
                a[j][k]=(a[j][k]-a[j][i]*a[i][k])%MOD;
                if(j==k)
                a[j][k]=(a[j][k]+MOD)%MOD;
            }
    }
    return ret;
}



int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        memset(degree,0,sizeof(degree));
        memset(g,0,sizeof(g));
        memset(a,0,sizeof(a));
        memset(p,0,sizeof(p));
        scanf("%d%d",&n,&R);
        for(int i=0;i<n;i++)
            p[i].input();

        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                if(check(i,j))
                {
                    degree[i]++;
                    degree[j]++;
                    g[j][i]=g[i][j]=1;
                }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                if(g[i][j]&&i!=j)
                    a[i][j]=-1;
            a[i][i]=degree[i];
        }
        ll ans=det(a,n-1);
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

N. SPOJ HIGH

技术分享
#include<time.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()


using namespace std;

const int MAXN=100;
const double eps=1e-18;

double a[MAXN][MAXN];
int b[MAXN][MAXN];

int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0)
        return -1;
    else
        return 1;
}
double det(double a[][MAXN],int n)
{
    double ret=1;
    int sign=0,i,j,k;
    for(i=0;i<n;i++)
    {
        if(sgn(a[i][i])==0)
        {
            for(j=i+1;j<n;j++)
                if(sgn(a[j][i]))
                    break;
            if(j==n) return 0;
            for(k=i;k<n;k++)
                swap(a[i][k],a[j][k]);
            sign++;
        }
        ret*=a[i][i];
        for(k=i+1;k<n;k++)
            a[i][k]/=a[i][i];
        for(j=i+1;j<n;j++)
            for(k=i+1;k<n;k++)
                a[j][k]-=a[j][i]*a[i][k];
    }

    if(sign&1)
        ret=-ret;
    return ret;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int T,n,m,u,v;
    scanf("%d",&T);
    while(T--)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        scanf("%d%d",&n,&m);
        while(m--)
        {
            scanf("%d%d",&u,&v);
            u--,v--;
            b[u][v]=b[v][u]=1;
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(i!=j&&b[i][j])
                {
                    a[i][i]++;
                    a[i][j]=-1;
                }
        double ans=det(a,n-1);
        printf("%.0lf\n",ans);
    }
    return 0;
}
View Code

 

[kuangbin带你飞]专题六 生成树

标签:

原文地址:http://www.cnblogs.com/onlyAzha/p/4802016.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!