第11章 图论模型与算法

再谈树

无根树转有根数

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100;
vector<int> G[maxn];
int n;
void read_tree(){
    int u,v;
    scanf("%d",&n);
    for(int i=0;i<n-1;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
}
int p[100];
void dfs(int u,int fa){//转化为u为根的子树,u的父结点为fa

    int d=G[u].size();
    for(int i=0;i<d;i++){
        int v=G[u][i];
        if(v!=fa) dfs(v,p[v]=u);
    }
}
int main()
{
    read_tree();
    for(int i=0;i<n-1;i++){ printf("%d:",i);
        for(int j=0;j<G[i].size();j++)
        printf("%d ",G[i][j]);
        printf("\n");
    }
    p[1]=-1;
    dfs(1,-1);
    for(int i=0;i<n;i++) printf("%d ",i); printf("\n");<pre name="code" class="cpp">const int maxn = 100;
int lch[maxn], rch[maxn]; char op[maxn]; //每个结点的左右子节点编号和字符
int nc=0; //结点数
int build_tree(char * s,int x,int y){
    int i,c1=-1,c2=-1,p=0;
    int u;
    if(y-x==1) { //进一个字符建立单独结点
        u = ++nc;
        lch[u]=rch[u]=0; op[u]=s[x];
        return u;
    }
    for(i=x;i<y;i++){
        switch(s[i]){
            case '(':p++;break;
            case ')':p--;break;
            case '+':case '-': if(!p) c1=i; break;
            case '*':case '/': if(!p) c2=i; break;
        }
    }
    if(c1<0) c1=c2;
    if(c1<0) return build_tree(s,x+1,y-1);
    u=++nc;
    lch[u]=build_tree(s,x,c1);
    ech[u]=build_tree(s,c1+1,y);
    op[u]=s[c1];
    return u;
}

for(int i=0;i<n;i++) printf("%d ",p[i]); printf("\n"); /* 初始的树 8 1 4 1 5 1 0 5 6 5 7 0 2 0 3 0:1 2 3 1:4 5 0 2:0 3:0 4:1 5:1 6 7 6:5 */ return 0;}

 

表达式树

const int maxn = 100;
int lch[maxn], rch[maxn]; char op[maxn]; //每个结点的左右子节点编号和字符
int nc=0; //结点数
int build_tree(char * s,int x,int y){
    int i,c1=-1,c2=-1,p=0;
    int u;
    if(y-x==1) { //进一个字符建立单独结点
        u = ++nc;
        lch[u]=rch[u]=0; op[u]=s[x];
        return u;
    }
    for(i=x;i<y;i++){
        switch(s[i]){
            case '(':p++;break;
            case ')':p--;break;
            case '+':case '-': if(!p) c1=i; break;
            case '*':case '/': if(!p) c2=i; break;
        }
    }
    if(c1<0) c1=c2;
    if(c1<0) return build_tree(s,x+1,y-1);
    u=++nc;
    lch[u]=build_tree(s,x,c1);
    ech[u]=build_tree(s,c1+1,y);
    op[u]=s[c1];
    return u;
}


例题11-1 公共表达式消除  uva12219

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 105;
struct Edge {
    int u,v,cost;
    bool operator < (const Edge& a) const {
        return cost > a.cost;
    }
};
int F[MAXN];int n,m;vector<Edge> edges;
int find(int x){
    return x==F[x]?x:F[x]=find(F[x]);
}
int kruskal(int k){
    for(int i=0;i<=n;i++) F[i]=i;
    int cnt=0;
    int minn=INF,maxn=0;
    for(int i=k;i<m;i++)
    {
        Edge e = edges[i];
        int v=e.v;
        int u=e.u;
        int fu=find(u);
        int fv=find(v);
        if(fu!=fv){
            cnt++;
            F[fu]=fv;
            minn=min(e.cost,minn);
            maxn =max(e.cost,maxn);
        }
    }
    if(cnt!=n-1)return -1;
    else return maxn-minn;
}



int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        edges.clear();
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            edges.push_back((Edge){a,b,c} );
        }
        sort(edges.begin(),edges.end());
        int ans=INF;
        for(int i=0;i<=m;i++){
            int t=kruskal(i);
            if(t==-1) break;
            ans = min(ans,t);
        }
        if(ans == INF) printf("%d\n",-1);
        else printf("%d\n",ans);
    }
    return 0;
}

例题11-3 买还是建 uva1151

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
struct point {
    int x,y;
}pp[maxn];
struct edge
{
    int s,e,dist;
}l[maxn*maxn];
int n,q,m;
int p[maxn];
vector<int> g[10];
int c[10];
int distance_(point a,point b){
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp(edge a,edge b){
    return a.dist < b.dist;
}
int find_(int x){
    return p[x]==x?x:p[x]=find_(p[x]);
}
bool merge_(int a,int b){
    int x=find_(a);
    int y=find_(b);
    if(x==y) return false;
    p[x]=y; return true;
}
int kruskal(){
    int ans=0;
    int num=0;
    for(int i=0;i<m&&num<n-1;i++)
    {
        if(merge_(l[i].s,l[i].e))
        {
            num++;
            ans += l[i].dist;
        }
    }
    return ans;
}
void solve(){
    for(int i=0;i<=n;i++) p[i]=i;
    int ans=kruskal();
    for(int s=1;s<(1<<q);s++){
        int cost=0;
        for(int tt=0;tt<=n;tt++) p[tt]=tt;
        for(int j=0;j<q;j++){
            if(!((s>>j)&1)) continue;
            cost += c[j];
            for(int k=0;k<g[j].size();k++)
            {
                merge_(g[j][k],g[j][0]);
            }
        }
        ans =min(ans, cost+kruskal());
    }
    printf("%d\n",ans);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        for(int i=0;i<10;i++) g[i].clear();
        for(int i=0;i<q;i++){
            int cnt;
            scanf("%d%d",&cnt,&c[i]);
            int a;
            for(int j=0;j<cnt;j++){
                scanf("%d",&a);
                g[i].push_back(a);
            }
        }
        for(int i=1;i<=n;i++){
            scanf("%d%d",&pp[i].x,&pp[i].y);
        }
        m=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                l[m].s=i;
                l[m].e=j;
                l[m++].dist=distance_(pp[i],pp[j]);
            }
        }
        sort(l,l+m,cmp);
        solve();
        if(t) printf("\n");
    }
    return 0;
}

Dijkstra算法:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值