poj 1087

二分图匹配+floyd求图中节点是否可达。模型很容易想到。此题我认为用网络流最好解释,如果有device有重复的话。二分图建模比较麻烦。一开始没想到这点,用二分图做的,但是AC了,数据应该没有device重复的情况。然后就是判断一个插头通过适配器能转化成什么其他的插头,刚开始用矩阵乘法来判断这个关系,数据一开到500运行时就运行错误(感觉也不是很大啊,至今还不知道原因),后来在网上发现有用floyd做,想了想,确实可以,而且还简单,就是个DP的过程。

 1     #include <iostream>
 2     #include <cstdio>
 3     #include <cstring>
 4     #include <cmath>
 5     #include <map>
 6     #include <string>
 7     using namespace std;
 8     const int maxn=500+10;
 9     int n,m,k,tot;
10     map<string,int> a1;
11     map<string,int> a2;
12     int bi[maxn][maxn];
13     int x[maxn],y[maxn],ch[maxn],mark[maxn];
14     int g[maxn][maxn];
15     int dfs(int u)
16     {
17         int v;
18         for(v=1;v<=n;v++)
19         {
20             if(bi[u][v]&&!ch[v])
21             {
22                 ch[v]=1;
23                 if(!y[v]||dfs(y[v]))
24                 {
25                     y[v]=u;x[u]=v;
26                     return 1;
27                 }
28                 //ch[v]=0; ch[v]不用置为0,从v没有增广路,以后不管那条只要走到v肯定还没有增广路,所以直接把他标记,省的以后再来搞她
29             }
30         }
31         return 0;
32     }
33     int MaxMatch()
34     {
35         memset(x,0,sizeof(x));
36         memset(y,0,sizeof(y));
37         int i,sum=0;
38         for(i=1;i<=m;i++)
39         {
40             memset(ch,0,sizeof(ch));
41             if(dfs(i)) sum++;
42         }
43         return sum;
44     }
45     void floyd()
46     {
47         int i,j,k;
48         for(k=1;k<=tot;k++)
49         {
50             for(i=1;i<=tot;i++)
51             {
52                 for(j=1;j<=tot;j++)
53                     g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
54             }
55         }
56     }
57     int main()
58     {
59         scanf("%d",&n);
60         int i;
61         string s1,s2;
62         tot=0;
63         for(i=0;i<n;i++)
64         {
65             cin>>s1;
66             a1[s1]=++tot;
67         }
68         scanf("%d",&m);
69         int u,v;
70         for(i=1;i<=m;i++)
71         {
72             cin>>s1>>s2;
73             if(!a1[s2]) a1[s2]=++tot;
74             v=a1[s2];
75             mark[i]=v;
76         }
77         scanf("%d",&k);
78         for(i=0;i<k;i++)
79         {
80             cin>>s1>>s2;
81             if(!a1[s1]) a1[s1]=++tot; if(!a1[s2]) a1[s2]=++tot;
82             u=a1[s1]; v=a1[s2];
83             g[u][v]=1;
84         }
85         for(i=1;i<=tot;i++) g[i][i]=1;
86         floyd();
87         for(i=1;i<=m;i++)
88         {
89             u=mark[i];
90             for(v=1;v<=n;v++)
91             {
92                 if(g[u][v]) bi[i][v]=1;
93             }
94         }
95         printf("%d\n",m-MaxMatch());
96         return 0;
97     }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值