zoukankan      html  css  js  c++  java
  • 最小树形图(有向图)

    GGS-DDU http://acm.hdu.edu.cn/showproblem.php?pid=4966

    建图待补,先做模板了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #define mt(a,b) memset(a,b,sizeof(a))
      4 const int inf=0x3f3f3f3f;
      5 class Directed_MST { ///最小树形图(有向图)
      6     typedef int typec;///边权的类型
      7     static const int ME=250010;///边的个数
      8     static const int MV=550;///点的个数
      9     struct E {
     10         int u,v;
     11         typec w;
     12     } e[ME];
     13     int n,le,pre[MV],ID[MV],vis[MV];
     14     typec In[MV];
     15 public:
     16     void init() {
     17         le=0;
     18     }
     19     void add(int u,int v,typec w) {
     20         e[le].u=u;
     21         e[le].v=v;
     22         e[le].w=w;
     23         le++;
     24     }
     25     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
     26         n=tn;
     27         typec ret=0;
     28         while(true) {
     29             for(int i=0; i<n; i++) {
     30                 In[i]=inf;
     31             }
     32             for(int i=0; i<le; i++) {
     33                 int u=e[i].u;
     34                 int v=e[i].v;
     35                 if(e[i].w<In[v]&&u!=v) {
     36                     pre[v]=u;
     37                     In[v]=e[i].w;
     38                 }
     39             }
     40             for(int i=0; i<n; i++) {
     41                 if(i==root) continue;
     42                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
     43             }
     44             int cntnode=0;///找环
     45             mt(ID,-1);
     46             mt(vis,-1);
     47             In[root]=0;
     48             for(int i=0; i<n; i++) { ///标记每个环
     49                 ret+=In[i];
     50                 int v=i;
     51                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
     52                     vis[v]=i;
     53                     v=pre[v];
     54                 }
     55                 if(v!=root&&ID[v]==-1) {
     56                     for(int u=pre[v]; u!=v; u=pre[u]) {
     57                         ID[u]=cntnode;
     58                     }
     59                     ID[v]=cntnode++;
     60                 }
     61             }
     62             if(!cntnode) break;///无环
     63             for(int i=0; i<n; i++) {
     64                 if(ID[i]==-1) {
     65                     ID[i]=cntnode++;
     66                 }
     67             }
     68             for(int i=0; i<le; i++) { ///缩点,重新标记
     69                 int v=e[i].v;
     70                 e[i].u=ID[e[i].u];
     71                 e[i].v=ID[e[i].v];
     72                 if(e[i].u!=e[i].v) {
     73                     e[i].w-=In[v];
     74                 }
     75             }
     76             n=cntnode;
     77             root=ID[root];
     78         }
     79         return ret;
     80     }
     81 } gx;
     82 int n,m,a[550],s[550];
     83 int main() {
     84     while(~scanf("%d%d",&n,&m),n|m){
     85         for(int i=0;i<n;i++){
     86             scanf("%d",&a[i]);
     87             a[i]++;
     88         }
     89         s[0]=0;
     90         for(int i=0;i<n;i++){
     91             s[i+1]=a[i]+s[i];
     92         }
     93         gx.init();
     94         for(int i=0;i<n;i++){
     95             for(int j=s[i+1]-1;j>s[i];j--){
     96                 gx.add(j,j-1,0);
     97             }
     98             gx.add(s[n],s[i],0);
     99         }
    100         while(m--){
    101             int a,L1,b,L2,cost;
    102             scanf("%d%d%d%d%d",&a,&L1,&b,&L2,&cost);
    103             a--;
    104             b--;
    105             a=s[a]+L1;
    106             b=s[b]+L2;
    107             gx.add(a,b,cost);
    108         }
    109         printf("%d
    ",gx.solve(s[n],s[n]+1));
    110     }
    111     return 0;
    112 }
    View Code

    Transfer water http://acm.hdu.edu.cn/showproblem.php?pid=4009

    待补,测模板。可以变根的,用邻接表存的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 typedef __int64 LL;
      7 const int inf=0x3f3f3f3f;
      8 const int M=1024;
      9 class Directed_MST { ///最小树形图(有向图)
     10     typedef int typec;///边权的类型
     11     static const int ME=M*M;///边的个数
     12     static const int MV=M;///点的个数
     13     struct E {
     14         int u,v;
     15         typec w;
     16     } e[ME];
     17     int n,le,pre[MV],ID[MV],vis[MV];
     18     typec In[MV];
     19 public:
     20     void init() {
     21         le=0;
     22     }
     23     void add(int u,int v,typec w) {
     24         e[le].u=u;
     25         e[le].v=v;
     26         e[le].w=w;
     27         le++;
     28     }
     29     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
     30         n=tn;
     31         typec ret=0;
     32         while(true) {
     33             for(int i=0; i<n; i++) {
     34                 In[i]=inf;
     35             }
     36             for(int i=0; i<le; i++) {
     37                 int u=e[i].u;
     38                 int v=e[i].v;
     39                 if(e[i].w<In[v]&&u!=v) {
     40                     pre[v]=u;
     41                     In[v]=e[i].w;
     42                 }
     43             }
     44             for(int i=0; i<n; i++) {
     45                 if(i==root) continue;
     46                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
     47             }
     48             int cntnode=0;///找环
     49             mt(ID,-1);
     50             mt(vis,-1);
     51             In[root]=0;
     52             for(int i=0; i<n; i++) { ///标记每个环
     53                 ret+=In[i];
     54                 int v=i;
     55                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
     56                     vis[v]=i;
     57                     v=pre[v];
     58                 }
     59                 if(v!=root&&ID[v]==-1) {
     60                     for(int u=pre[v]; u!=v; u=pre[u]) {
     61                         ID[u]=cntnode;
     62                     }
     63                     ID[v]=cntnode++;
     64                 }
     65             }
     66             if(!cntnode) break;///无环
     67             for(int i=0; i<n; i++) {
     68                 if(ID[i]==-1) {
     69                     ID[i]=cntnode++;
     70                 }
     71             }
     72             for(int i=0; i<le; i++) { ///缩点,重新标记
     73                 int v=e[i].v;
     74                 e[i].u=ID[e[i].u];
     75                 e[i].v=ID[e[i].v];
     76                 if(e[i].u!=e[i].v) {
     77                     e[i].w-=In[v];
     78                 }
     79             }
     80             n=cntnode;
     81             root=ID[root];
     82         }
     83         return ret;
     84     }
     85 } gx;
     86 int ha[M],hb[M],hc[M];
     87 int X,Y,Z;
     88 int dist(int i, int j) {
     89     int ret = abs(ha[i] - ha[j]) + abs(hb[i] - hb[j]) + abs(hc[i] - hc[j]);
     90     ret *= Y;
     91     if (hc[i] < hc[j]) ret += Z;
     92     return ret;
     93 }
     94 int main(){
     95     int n;
     96     while(~scanf("%d%d%d%d",&n,&X,&Y,&Z),n+X+Y+Z) {
     97         n++;
     98         gx.init();
     99         for (int i = 2; i <= n; i++) scanf("%d %d %d", &ha[i], &hb[i], &hc[i]);
    100         for (int i = 2; i <= n; i++) {
    101             gx.add(0,i-1,hc[i]*X);
    102             int k;
    103             scanf("%d", &k);
    104             while (k--) {
    105                 int j;
    106                 scanf("%d", &j);
    107                 j++;
    108                 if (j != i) {
    109                     int c = dist(i, j);
    110                     gx.add(i-1,j-1,c);
    111                 }
    112             }
    113         }
    114         int ans=gx.solve(0,n);
    115         if (ans==-1) puts("Impossible");
    116         else printf("%d
    ",ans);
    117     }
    118     return 0;
    119 }
    View Code

     根为1,矩阵存的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 typedef __int64 LL;
      7 const int inf=0x3f3f3f3f;
      8 class Directed_MST_Matrix { ///最小树形图(有向图邻接阵)o(MV*ME)
      9     typedef int typec;///边权的类型
     10     static const int MV=1024;///点的个数
     11     int s,l,r,n,id[MV],mark[MV],pre[MV],f[MV];
     12     bool vis[MV];///g[][]边权初始化为-1,结果ans为-1表示不存在
     13     typec g[MV][MV],ans,mincost[MV];
     14     void dfs(int v) {
     15         s++;
     16         vis[v]=true;
     17         for(int i=1; i<=n; i++) {
     18             if(!vis[i]&&g[v][i]!=-1)
     19                 dfs(i);
     20         }
     21     }
     22     void combine() {
     23         mt(vis,0);
     24         for(int i=l; i<=r; i++)
     25             vis[f[i]]=true;
     26         int now=f[l];
     27         for(int i=l; i<=r; i++) {
     28             int x=f[i];
     29             ans+=mincost[x];
     30             id[x]=now;
     31             for(int j=1; j<=n; j++) {
     32                 if(!vis[j]&&id[j]==j) {
     33                     if(g[j][x]!=-1) {
     34                         typec tmp=g[j][x]-mincost[x];
     35                         if(g[j][now]==-1||tmp<g[j][now])
     36                             g[j][now]=tmp;
     37                     }
     38                     if((g[x][j]!=-1&&g[x][j]<g[now][j])||g[now][j]==-1)
     39                         g[now][j]=g[x][j];
     40                 }
     41             }
     42         }
     43         for(int i=2; i<=n; i++)
     44             if(id[i]==i)
     45                 pre[i]=id[pre[i]];
     46         mincost[now]=inf;
     47         for(int i=1; i<=n; i++) {
     48             if(id[i]==i&&i!=now&&g[i][now]!=-1&&g[i][now]<mincost[now]) {
     49                 mincost[now]=g[i][now];
     50                 pre[now]=i;
     51             }
     52         }
     53     }
     54     bool find_circle() {
     55         mt(vis,0);
     56         for(int k=2; k<=n; k++) {
     57             if(!vis[k]&&id[k]==k) {
     58                 mt(mark,0);
     59                 int i=k;
     60                 r=0;
     61                 while(i!=1&&!mark[i]&&!vis[i]) {
     62                     r++;
     63                     f[r]=i;
     64                     mark[i]=r;
     65                     vis[i]=true;
     66                     i=pre[i];
     67                 }
     68                 if (mark[i]) {
     69                     l=mark[i];
     70                     return true;
     71                 }
     72             }
     73         }
     74         return false;
     75     }
     76 public:
     77     void init(int tn) { ///传入点数,下标1开始,生成以1为根的有向树
     78         n=tn;
     79         for(int i=1; i<=n; i++)
     80             for(int j=1; j<=n; j++)
     81                 g[i][j]=i==j?0:-1;
     82     }
     83     void add(int u,int v,typec w) {
     84         if(g[u][v]==-1||g[u][v]>w) {
     85             g[u][v]=w;
     86         }
     87     }
     88     typec solve() {
     89         mt(vis,0);
     90         s=0;
     91         dfs(1);
     92         if (s<n) {
     93             return -1;
     94         } else {
     95             id[1]=1;
     96             for(int i=2; i<=n; i++) {
     97                 id[i]=i;
     98                 mincost[i]=inf;
     99                 for(int j=1; j<=n; j++) {
    100                     if(j!=i&&g[j][i]!=-1&&g[j][i]<mincost[i]) {
    101                         mincost[i]=g[j][i];
    102                         pre[i]=j;
    103                     }
    104                 }
    105             }
    106             ans=0;
    107         }
    108         while (find_circle()) combine();
    109         for(int i=2; i<=n; i++)
    110             if (id[i]==i)
    111                 ans+=mincost[i];
    112         return ans;
    113     }
    114 }gx;
    115 const int M=1024;
    116 int ha[M],hb[M],hc[M];
    117 int X,Y,Z;
    118 int dist(int i, int j) {
    119     int ret = abs(ha[i] - ha[j]) + abs(hb[i] - hb[j]) + abs(hc[i] - hc[j]);
    120     ret *= Y;
    121     if (hc[i] < hc[j]) ret += Z;
    122     return ret;
    123 }
    124 int main() {
    125     int n;
    126     while(~scanf("%d%d%d%d",&n,&X,&Y,&Z),n+X+Y+Z) {
    127         n++;
    128         gx.init(n);
    129         for (int i = 2; i <= n; i++) scanf("%d %d %d", &ha[i], &hb[i], &hc[i]);
    130         for (int i = 2; i <= n; i++) {
    131             gx.add(1,i,hc[i]*X);
    132             int k;
    133             scanf("%d", &k);
    134             while (k--) {
    135                 int j;
    136                 scanf("%d", &j);
    137                 j++;
    138                 if (j != i) {
    139                     int c = dist(i, j);
    140                     gx.add(i,j,c);
    141                 }
    142             }
    143         }
    144         int ans=gx.solve();
    145         if (ans==-1) puts("Impossible");
    146         else printf("%d
    ",ans);
    147     }
    148     return 0;
    149 }
    View Code

    Command Network http://poj.org/problem?id=3164

    距离建图,权值是double,模板题。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 const int inf=0x3f3f3f3f;
      6 const int M=128;
      7 class Directed_MST { ///最小树形图(有向图)
      8     typedef double typec;///边权的类型
      9     static const int ME=M*M;///边的个数
     10     static const int MV=M;///点的个数
     11     struct E {
     12         int u,v;
     13         typec w;
     14     } e[ME];
     15     int n,le,pre[MV],ID[MV],vis[MV];
     16     typec In[MV];
     17 public:
     18     void init() {
     19         le=0;
     20     }
     21     void add(int u,int v,typec w) {
     22         e[le].u=u;
     23         e[le].v=v;
     24         e[le].w=w;
     25         le++;
     26     }
     27     typec solve(int root,int tn) {///传入根和点的个数,点下标0开始
     28         n=tn;
     29         typec ret=0;
     30         while(true) {
     31             for(int i=0; i<n; i++) {
     32                 In[i]=inf;
     33             }
     34             for(int i=0; i<le; i++) {
     35                 int u=e[i].u;
     36                 int v=e[i].v;
     37                 if(e[i].w<In[v]&&u!=v) {
     38                     pre[v]=u;
     39                     In[v]=e[i].w;
     40                 }
     41             }
     42             for(int i=0; i<n; i++) {
     43                 if(i==root) continue;
     44                 if(In[i]==inf) return -1;///除了根以外有点没有入边,则根无法到达它
     45             }
     46             int cntnode=0;///找环
     47             mt(ID,-1);
     48             mt(vis,-1);
     49             In[root]=0;
     50             for(int i=0; i<n; i++) { ///标记每个环
     51                 ret+=In[i];
     52                 int v=i;
     53                 while(vis[v]!=i&&ID[v]==-1&&v!=root) {
     54                     vis[v]=i;
     55                     v=pre[v];
     56                 }
     57                 if(v!=root&&ID[v]==-1) {
     58                     for(int u=pre[v]; u!=v; u=pre[u]) {
     59                         ID[u]=cntnode;
     60                     }
     61                     ID[v]=cntnode++;
     62                 }
     63             }
     64             if(!cntnode) break;///无环
     65             for(int i=0; i<n; i++) {
     66                 if(ID[i]==-1) {
     67                     ID[i]=cntnode++;
     68                 }
     69             }
     70             for(int i=0; i<le; i++) { ///缩点,重新标记
     71                 int v=e[i].v;
     72                 e[i].u=ID[e[i].u];
     73                 e[i].v=ID[e[i].v];
     74                 if(e[i].u!=e[i].v) {
     75                     e[i].w-=In[v];
     76                 }
     77             }
     78             n=cntnode;
     79             root=ID[root];
     80         }
     81         return ret;
     82     }
     83 } gx;
     84 struct point{
     85     double x,y;
     86 }p[M];
     87 double Distance(point p1,point p2) {
     88     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
     89 }
     90 int main(){
     91     int n,m,u,v;
     92     while(~scanf("%d%d",&n,&m)){
     93         for(int i=0;i<n;i++){
     94             scanf("%lf%lf",&p[i].x,&p[i].y);
     95         }
     96         gx.init();
     97         while(m--){
     98             scanf("%d%d",&u,&v);
     99             u--;
    100             v--;
    101             gx.add(u,v,Distance(p[u],p[v]));
    102         }
    103         double ans=gx.solve(0,n);
    104         if(ans==-1) puts("poor snoopy");
    105         else printf("%.2f
    ",ans);
    106     }
    107     return 0;
    108 }
    View Code

     用矩阵的模板来测测。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 const int inf=0x3f3f3f3f;
      6 const int M=128;
      7 class Directed_MST_Matrix { ///最小树形图(有向图邻接阵)o(MV*ME)
      8     typedef double typec;///边权的类型
      9     static const int MV=128;///点的个数
     10     int s,l,r,n,id[MV],mark[MV],pre[MV],f[MV];
     11     bool vis[MV];///g[][]边权初始化为-1,结果ans为-1表示不存在
     12     typec g[MV][MV],ans,mincost[MV];
     13     void dfs(int v) {
     14         s++;
     15         vis[v]=true;
     16         for(int i=1; i<=n; i++) {
     17             if(!vis[i]&&g[v][i]!=-1)
     18                 dfs(i);
     19         }
     20     }
     21     void combine() {
     22         mt(vis,0);
     23         for(int i=l; i<=r; i++)
     24             vis[f[i]]=true;
     25         int now=f[l];
     26         for(int i=l; i<=r; i++) {
     27             int x=f[i];
     28             ans+=mincost[x];
     29             id[x]=now;
     30             for(int j=1; j<=n; j++) {
     31                 if(!vis[j]&&id[j]==j) {
     32                     if(g[j][x]!=-1) {
     33                         typec tmp=g[j][x]-mincost[x];
     34                         if(g[j][now]==-1||tmp<g[j][now])
     35                             g[j][now]=tmp;
     36                     }
     37                     if((g[x][j]!=-1&&g[x][j]<g[now][j])||g[now][j]==-1)
     38                         g[now][j]=g[x][j];
     39                 }
     40             }
     41         }
     42         for(int i=2; i<=n; i++)
     43             if(id[i]==i)
     44                 pre[i]=id[pre[i]];
     45         mincost[now]=inf;
     46         for(int i=1; i<=n; i++) {
     47             if(id[i]==i&&i!=now&&g[i][now]!=-1&&g[i][now]<mincost[now]) {
     48                 mincost[now]=g[i][now];
     49                 pre[now]=i;
     50             }
     51         }
     52     }
     53     bool find_circle() {
     54         mt(vis,0);
     55         for(int k=2; k<=n; k++) {
     56             if(!vis[k]&&id[k]==k) {
     57                 mt(mark,0);
     58                 int i=k;
     59                 r=0;
     60                 while(i!=1&&!mark[i]&&!vis[i]) {
     61                     r++;
     62                     f[r]=i;
     63                     mark[i]=r;
     64                     vis[i]=true;
     65                     i=pre[i];
     66                 }
     67                 if (mark[i]) {
     68                     l=mark[i];
     69                     return true;
     70                 }
     71             }
     72         }
     73         return false;
     74     }
     75 public:
     76     void init(int tn) { ///传入点数,下标1开始,生成以1为根的有向树
     77         n=tn;
     78         for(int i=1; i<=n; i++)
     79             for(int j=1; j<=n; j++)
     80                 g[i][j]=i==j?0:-1;
     81     }
     82     void add(int u,int v,typec w) {
     83         if(g[u][v]==-1||g[u][v]>w) {
     84             g[u][v]=w;
     85         }
     86     }
     87     typec solve() {
     88         mt(vis,0);
     89         s=0;
     90         dfs(1);
     91         if (s<n) {
     92             return -1;
     93         } else {
     94             id[1]=1;
     95             for(int i=2; i<=n; i++) {
     96                 id[i]=i;
     97                 mincost[i]=inf;
     98                 for(int j=1; j<=n; j++) {
     99                     if(j!=i&&g[j][i]!=-1&&g[j][i]<mincost[i]) {
    100                         mincost[i]=g[j][i];
    101                         pre[i]=j;
    102                     }
    103                 }
    104             }
    105             ans=0;
    106         }
    107         while (find_circle()) combine();
    108         for(int i=2; i<=n; i++)
    109             if (id[i]==i)
    110                 ans+=mincost[i];
    111         return ans;
    112     }
    113 }gx;
    114 struct point{
    115     double x,y;
    116 }p[M];
    117 double Distance(point p1,point p2) {
    118     return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
    119 }
    120 int main(){
    121     int n,m,u,v;
    122     while(~scanf("%d%d",&n,&m)){
    123         for(int i=1;i<=n;i++){
    124             scanf("%lf%lf",&p[i].x,&p[i].y);
    125         }
    126         gx.init(n);
    127         while(m--){
    128             scanf("%d%d",&u,&v);
    129             gx.add(u,v,Distance(p[u],p[v]));
    130         }
    131         double ans=gx.solve();
    132         if(ans==-1) puts("poor snoopy");
    133         else printf("%.2f
    ",ans);
    134     }
    135     return 0;
    136 }
    View Code

    end

  • 相关阅读:
    【老孙随笔】项目经理要如何看待技术?
    从菜鸟到CTO——你的目标需要管理
    FormatX源代码格式化插件V2.0版
    JavaScript面向对象之静态与非静态类
    FormatX源代码格式化插件
    正确捕获 WCF服务调用中发生的异常及处理技巧
    2010,应该感谢的那些人以及那些未完成的事
    使用IErrorHandle对WCF服务器进行异常处理
    代码重构之路的艰辛
    从读取Excel文件引申出的问题(上)
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3945256.html
Copyright © 2011-2022 走看看