最短路二分图匹配树形背包DPDay 10.8

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路二分图匹配树形背包DPDay 10.8相关的知识,希望对你有一定的参考价值。

T1

最短路

  1 #include <cstdio>
  2 #include <queue>
  3 #include <iostream>
  4 #include <cstring>
  5 using namespace std;
  6 typedef pair<int,int> P;
  7 typedef pair<int,P> R;
  8 priority_queue<R,vector<R>,greater<R> > que;
  9 int m,n,a2,b2,a3,b3,ans=2000000000,sans[10001],a[101][101],cut[101][101],reg[101][101],b[101][101],pre[101][01],d[5]={1,0,-1,0,1},d2[4]={3,2,0,1};
 10 char ch,map[101][101];
 11 void bfsa()//老师 
 12 {
 13     memset(reg,0,sizeof(reg));
 14     while(!que.empty())
 15     {
 16         R x=que.top();que.pop();
 17         P y=x.second;
 18         if (reg[y.first][y.second]) continue;
 19         reg[y.first][y.second]=1;
 20         for (int i=0;i<4;i++)
 21         {
 22             int a1=y.first+d[i],b1=y.second+d[i+1];
 23             if (a1<1||a1>m||b1<1||b1>n||map[a1][b1]==#) continue;
 24             if (a[a1][b1]==-1||a[a1][b1]>a[y.first][y.second]+1)
 25             {
 26                 a[a1][b1]=a[y.first][y.second]+1;
 27                 que.push(R(a[a1][b1],P(a1,b1)));
 28             }
 29         }
 30     }
 31 }
 32 void bfsb()//学生 
 33 {
 34     que.push(R(0,P(a2,b2)));
 35     memset(reg,0,sizeof(reg));
 36     while(!que.empty())
 37     {
 38         R x=que.top();que.pop();
 39         P y=x.second;
 40         if (reg[y.first][y.second]) continue;
 41         reg[y.first][y.second]=1;
 42         for (int j=0;j<4;j++)
 43         {
 44             int i=d2[j];
 45             int a1=y.first+d[i],b1=y.second+d[i+1];
 46             if (a1<1||a1>m||b1<1||b1>n||map[a1][b1]==#) continue;
 47             if ((b[y.first][y.second]+1)/4<a[a1][b1]&&(b[a1][b1]==-1||b[a1][b1]>b[y.first][y.second]+1))
 48             {
 49                 b[a1][b1]=b[y.first][y.second]+1;
 50                 que.push(R(b[a1][b1],P(a1,b1)));
 51             }
 52         }
 53     }
 54 }
 55 void bfsc()//反向剪枝 
 56 {
 57     que.push(R(ans,P(a3,b3)));
 58     memset(reg,0,sizeof(reg));
 59     while(!que.empty())
 60     {
 61         R x=que.top();que.pop();
 62         P y=x.second;
 63         cut[y.first][y.second]=0;
 64         if (reg[y.first][y.second]) continue;
 65         reg[y.first][y.second]=1;
 66         for (int j=0;j<4;j++)
 67         {
 68             int i=d2[j];
 69             int a1=y.first+d[i],b1=y.second+d[i+1];
 70             if (a1<1||a1>m||b1<1||b1>n||map[a1][b1]==#) continue;
 71             if (b[a1][b1]==b[y.first][y.second]-1)
 72                 que.push(R(b[a1][b1],P(a1,b1)));
 73         }
 74     } 
 75 }
 76 void dfs(int x,int y)//找字典序最小 
 77 {
 78     int cnt=0;
 79     while(x>=1&&x<=m&&y>=1&&y<=n)
 80     {
 81         if (cnt==ans) break;
 82         for (int i=0;i<4;i++)
 83         {
 84             int j=d2[i];
 85             if (cut[x+d[j]][y+d[j+1]]==0&&b[x+d[j]][y+d[j+1]]==b[x][y]+1)
 86             {
 87                 x=x+d[j];y=y+d[j+1];
 88                 sans[cnt++]=i;
 89                 break;
 90             }
 91         }
 92     }
 93 }
 94 int main()
 95 {
 96     freopen("Run.in","r",stdin);
 97     freopen("Run.out","w",stdout);
 98     memset(a,-1,sizeof(a));
 99     memset(b,-1,sizeof(b));
100     memset(cut,-1,sizeof(cut));
101     scanf("%d%d",&m,&n);
102     for (int i=1;i<=m;i++)
103     {
104         getchar();
105         for (int j=1;j<=n;j++)
106         {
107             scanf("%c",&ch);
108             map[i][j]=ch;
109             if (ch==Z||ch==J||ch==T||ch==C)
110             {a[i][j]=0;que.push(R(0,P(i,j)));}
111             if (ch==P) a2=i,b2=j,b[i][j]=0;
112         }
113     }
114     bfsa();
115     bfsb();
116     for (int i=1;i<=m;i++) for (int j=1;j<=n;j++)
117         if ((i==1||i==m||j==1||j==n)&&b[i][j]!=-1) {ans=b[i][j];a3=i,b3=j;}
118     if (ans==2000000000){printf("I am so sorry\n");return 0;}
119     printf("%d\n",ans+1);
120     bfsc();
121     dfs(a2,b2);
122     sans[ans]=sans[ans-1];
123     for (int i=0;i<=ans;i++)
124     {
125         if (sans[i]==0) printf("E");
126         if (sans[i]==1) printf("N");
127         if (sans[i]==2) printf("S");
128         if (sans[i]==3) printf("W");
129     }
130 }

 

T2

二分图匹配

 1 #include <cstdio>
 2 #include <cstring>
 3 int x,y,m,f,in[1001],ans=0,girl[1001],line[1001][1001];
 4 bool find(int x)
 5 {
 6     for (int i=1;i<=f;i++)
 7     {
 8         if (line[x][i]==2&&!in[i])
 9         {
10             in[i]=1;
11             if (girl[i]==0||find(girl[i]))
12             {
13                 girl[i]=x;
14                 return 1;
15             }
16         }
17     }
18     return 0;
19 }
20 int main()
21 {
22     freopen("Seat.in","r",stdin);
23     freopen("Seat.out","w",stdout);
24     scanf("%d%d",&m,&f);
25     for (int i=1;i<=m;i++){
26         scanf("%d",&x);
27         for (int j=1;j<=x;j++){
28             scanf("%d",&y);
29             line[i][y]++;
30         }
31     }
32     for (int i=1;i<=f;i++){
33         scanf("%d",&x);
34         for (int j=1;j<=x;j++){
35             scanf("%d",&y);
36             line[y][i]++;
37         }
38     }
39     for (int i=1;i<=m;i++)
40     {
41         memset(in,0,sizeof(in));
42         if (find(i)) ans++;
43     }
44     printf("%d",ans);
45 }

 

T3

树形背包DP

 1 #include <cstdio>
 2 #include <vector>
 3 #include <iostream>
 4 #include <map>
 5 #include <vector>
 6 using namespace std;
 7 int m,n,p,x,y;
 8 int a[101],b[101],nrt[101],f[101][1001];
 9 string s,s2;
10 map<string,int> mp;
11 vector<int> ve[101];
12 void dfs(int x)
13 {
14     if (x!=0) for (int i=a[x];i<=p;i++) f[x][i]=b[x];
15     for (int i=0;i<ve[x].size();i++)//分组 
16     {
17         dfs(ve[x][i]);
18         for (int j=p;j>=a[x];j--)//当前背包的大小 
19         {
20             for (int k=0;k<=j;k++)//每个组里的元素 
21             {
22                 if (j-k>=a[x]) f[x][j]=max(f[x][j],f[x][j-k]+f[ve[x][i]][k]);
23             } 
24         }
25     }
26 }
27 int main()
28 {
29     freopen("Budget.in","r",stdin);
30     freopen("Budget.out","w",stdout);
31     cin>>m>>n>>p;
32     for (int i=1;i<=m;i++)
33     {
34         cin>>a[i]>>b[i]>>s;
35         mp[s]=i;
36     }
37     for (int i=1;i<=n;i++)
38     {
39         cin>>s>>s2;
40         nrt[mp[s2]]=1;
41         ve[mp[s]].push_back(mp[s2]);
42     }
43     for (int i=1;i<=m;i++)
44         if (!nrt[i]) ve[0].push_back(i);
45     dfs(0);
46     printf("%d",f[0][p]);
47 }

 

以上是关于最短路二分图匹配树形背包DPDay 10.8的主要内容,如果未能解决你的问题,请参考以下文章

POJ3057 Evacuation 二分图匹配+最短路

POJ3057 Evacuation 二分图匹配+最短路

最短路思想实现一般图最大匹配

二分图匹配入门专题1I - Hiding Gold light oj 1152二分图匹配-------------------我是终于不那么水的水题分割线------------------(代码片

noip知识点

网络流常见建图套路总结(重制版)