专题训练之强连通分量和2-sat

tarjan模板

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=20010;
 6 const int maxm=50010;
 7 struct edge{
 8     int to,nxt;
 9 }edge[maxm];
10 int head[maxn],tot;
11 int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
12 int index,top;
13 int scc;
14 bool vis[maxn];
15 int num[maxn];
16
17 void addedge(int u,int v)
18 {
19     edge[tot].to=v;
20     edge[tot].nxt=head[u];
21     head[u]=tot++;
22 }
23
24 void tarjan(int u)
25 {
26     int v;
27     low[u]=dfn[u]=++index;
28     stack[top++]=u;
29     vis[u]=true;
30     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
31         v=edge[i].to;
32         if ( !dfn[v] ) {
33             tarjan(v);
34             low[u]=min(low[u],low[v]);
35         }
36         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
37     }
38     if ( low[u]==dfn[u] ) {
39         scc++;
40         do {
41             v=stack[--top];
42             vis[v]=false;
43             belong[v]=scc;
44             num[scc]++;
45         }
46         while ( v!=u );
47     }
48 }
49
50 void solve(int N)
51 {
52     memset(dfn,0,sizeof(dfn));
53     memset(vis,false,sizeof(vis));
54     memset(num,0,sizeof(num));
55     index=scc=top=0;
56     for ( int i=1;i<=N;i++ ) {
57         if ( !dfn[i] ) tarjan(i);
58     }
59 }
60
61 void init()
62 {
63     tot=0;
64     memset(head,-1,sizeof(head));
65 }

tarjan模板

1.(HDOJ1269)http://acm.hdu.edu.cn/showproblem.php?pid=1269

分析:裸题,判断scc是否为1即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e4+10;
 6 const int maxm=1e5+10;
 7 struct edge{
 8     int to,nxt;
 9 }edge[maxm];
10 int head[maxn],tot;
11 int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
12 int index,top;
13 int scc,n;
14 bool vis[maxn];
15 int num[maxn];
16
17 void addedge(int u,int v)
18 {
19     edge[tot].to=v;
20     edge[tot].nxt=head[u];
21     head[u]=tot++;
22 }
23
24 void tarjan(int u)
25 {
26     int v;
27     low[u]=dfn[u]=++index;
28     stack[top++]=u;
29     vis[u]=true;
30     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
31         v=edge[i].to;
32         if ( !dfn[v] ) {
33             tarjan(v);
34             low[u]=min(low[u],low[v]);
35         }
36         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
37     }
38     if ( low[u]==dfn[u] ) {
39         scc++;
40         do {
41             v=stack[--top];
42             vis[v]=false;
43             belong[v]=scc;
44             num[scc]++;
45         }
46         while ( v!=u );
47     }
48 }
49
50 void solve()
51 {
52     memset(dfn,0,sizeof(dfn));
53     memset(vis,false,sizeof(vis));
54     memset(num,0,sizeof(num));
55     index=scc=top=0;
56     for ( int i=1;i<=n;i++ ) {
57         if ( !dfn[i] ) tarjan(i);
58     }
59 }
60
61 void init()
62 {
63     tot=0;
64     memset(head,-1,sizeof(head));
65 }
66
67 int main()
68 {
69     int m,i,j,k,x,y;
70     while ( scanf("%d%d",&n,&m)!=EOF && (n+m) ) {
71         init();
72         for ( i=0;i<m;i++ ) {
73             scanf("%d%d",&x,&y);
74             addedge(x,y);
75         }
76         solve();
77         if ( scc==1 ) printf("Yes\n");
78         else printf("No\n");
79     }
80     return 0;
81  } 

HDOJ1269

2.(HDOJ1827)http://acm.hdu.edu.cn/showproblem.php?pid=1827

分析:利用tarjan进行缩点得到新的GAD图,然后再根据新图中每个节点的入度和出度进行相应的操作。因为该题需要花费更少,所有只需要求那些所有入度为0的点所需要花费的费用。而对于新图中每个点的花费,可以很方便的在tarjan中进行更新

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=1005;
  6 const int maxm=2005;
  7 const int inf=1e9;
  8 struct edge{
  9     int to,nxt;
 10 }edge[maxm];
 11 int head[maxn],tot;
 12 int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
 13 int index,top;
 14 int scc,n;
 15 bool vis[maxn];
 16 int num[maxn];
 17 int cost[maxn],in[maxn],out[maxn],cost_[maxn];
 18
 19 void addedge(int u,int v)
 20 {
 21     edge[tot].to=v;
 22     edge[tot].nxt=head[u];
 23     head[u]=tot++;
 24 }
 25
 26 void tarjan(int u)
 27 {
 28     int v;
 29     low[u]=dfn[u]=++index;
 30     stack[top++]=u;
 31     vis[u]=true;
 32     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
 33         v=edge[i].to;
 34         if ( !dfn[v] ) {
 35             tarjan(v);
 36             low[u]=min(low[u],low[v]);
 37         }
 38         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
 39     }
 40     if ( low[u]==dfn[u] ) {
 41         scc++;
 42         do {
 43             v=stack[--top];
 44             vis[v]=false;
 45             belong[v]=scc;
 46             num[scc]++;
 47             cost_[scc]=min(cost_[scc],cost[v]);
 48         }
 49         while ( v!=u );
 50     }
 51 }
 52
 53 void solve()
 54 {
 55     memset(dfn,0,sizeof(dfn));
 56     memset(vis,false,sizeof(vis));
 57     memset(num,0,sizeof(num));
 58     for ( int i=1;i<=n;i++ ) cost_[i]=inf;
 59     index=scc=top=0;
 60     for ( int i=1;i<=n;i++ ) {
 61         if ( !dfn[i] ) tarjan(i);
 62     }
 63 }
 64
 65 void init()
 66 {
 67     tot=0;
 68     memset(head,-1,sizeof(head));
 69 }
 70
 71 int main()
 72 {
 73     int m,i,j,k,x,y,ans,cnt,v;
 74     while ( scanf("%d%d",&n,&m)!=EOF ) {
 75         init();
 76         for ( i=1;i<=n;i++ ) scanf("%d",&cost[i]);
 77         for ( i=1;i<=m;i++ ) {
 78             scanf("%d%d",&x,&y);
 79             addedge(x,y);
 80         }
 81         solve();
 82         memset(in,0,sizeof(in));
 83         memset(out,0,sizeof(out));
 84         for ( i=1;i<=n;i++ ) {
 85             for ( j=head[i];j!=-1;j=edge[j].nxt ) {
 86                 v=edge[j].to;
 87                 if ( belong[i]!=belong[v] ) {
 88                     in[belong[v]]++;
 89                     out[belong[i]]++;
 90                 }
 91             }
 92         }
 93         ans=0;
 94         cnt=0;
 95         for ( i=1;i<=scc;i++ ) {
 96             if ( !in[i] ) {
 97                 ans+=cost_[i];
 98                 cnt++;
 99             }
100         }
101         printf("%d %d\n",cnt,ans);
102     }
103     return 0;
104 }

HDOJ1827

3.(HDOJ2767、HDOJ3836)

http://acm.hdu.edu.cn/showproblem.php?pid=2767

http://acm.hdu.edu.cn/showproblem.php?pid=3836

题意:添加多少条可以使得整个图为一个强连通分量。先求出强连通分量的个数,然后需要添加的边为出度和入度为0中较大的那个值(即没有点的入度和出度为0)。需要特别注意的是本身只有一个强连通分量则直接输出0

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=20050;
  6 const int maxm=50010;
  7 struct edge{
  8     int to,nxt;
  9 }edge[maxm];
 10 int head[maxn],tot;
 11 int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
 12 int index,top;
 13 int scc;
 14 bool vis[maxn];
 15 int num[maxn],in[maxn],out[maxn];
 16
 17 void addedge(int u,int v)
 18 {
 19     edge[tot].to=v;
 20     edge[tot].nxt=head[u];
 21     head[u]=tot++;
 22 }
 23
 24 void tarjan(int u)
 25 {
 26     int v;
 27     low[u]=dfn[u]=++index;
 28     stack[top++]=u;
 29     vis[u]=true;
 30     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
 31         v=edge[i].to;
 32         if ( !dfn[v] ) {
 33             tarjan(v);
 34             low[u]=min(low[u],low[v]);
 35         }
 36         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
 37     }
 38     if ( low[u]==dfn[u] ) {
 39         scc++;
 40         do {
 41             v=stack[--top];
 42             vis[v]=false;
 43             belong[v]=scc;
 44             num[scc]++;
 45         }
 46         while ( v!=u );
 47     }
 48 }
 49
 50 void solve(int N)
 51 {
 52     memset(dfn,0,sizeof(dfn));
 53     memset(vis,false,sizeof(vis));
 54     memset(num,0,sizeof(num));
 55     index=scc=top=0;
 56     for ( int i=1;i<=N;i++ ) {
 57         if ( !dfn[i] ) tarjan(i);
 58     }
 59 }
 60
 61 void init()
 62 {
 63     tot=0;
 64     memset(head,-1,sizeof(head));
 65 }
 66
 67 int main()
 68 {
 69     int T,i,j,k,n,m,x,y,z,ans,cnt1,cnt2;
 70     scanf("%d",&T);
 71     while ( T-- ) {
 72         init();
 73         scanf("%d%d",&n,&m);
 74         while ( m-- ) {
 75             scanf("%d%d",&x,&y);
 76             addedge(x,y);
 77         }
 78         solve(n);
 79         memset(in,0,sizeof(in));
 80         memset(out,0,sizeof(out));
 81         for ( i=1;i<=n;i++ ) {
 82             for ( j=head[i];j!=-1;j=edge[j].nxt ) {
 83                 int v=edge[j].to;
 84                 if ( belong[v]!=belong[i] ) {
 85                     in[belong[v]]++;
 86                     out[belong[i]]++;
 87                 }
 88             }
 89         }
 90         cnt1=cnt2=0;
 91         for ( i=1;i<=scc;i++ ) {
 92             if ( in[i]==0 ) cnt1++;
 93             if ( out[i]==0 ) cnt2++;
 94         }
 95         ans=max(cnt1,cnt2);
 96         if ( scc==1 ) ans=0;
 97         printf("%d\n",ans);
 98     }
 99     return 0;
100  } 

HDOJ2767

4.(HDOJ3639)http://acm.hdu.edu.cn/showproblem.php?pid=3639

题意:有n个小孩要相互投票,有m条两人之间的单向的支持关系,求获得支持最多的人的支持数,并要求把这些人的编号(0~n-1)按升序排列输出来。

分析:首先利用tarjan进行缩点构建新图,首先明确得票数最高的人一定在出度为0的强连通分量团体中,所以当前任务就是确定对于每个出度为0的强连通分量团体有多少人能够直接或间接指向它们。这时候就要在新图上构建反向边,对于出度为0的点i进行搜索,经过的所有点的人数总和(每个点都代表一部分人数)就是支持这个团体i中每个人的总得票数。记录每个出度为0的点的得票数,取最大值。最后对于新图中的每个点当其的得票数为最大值时,其强连通分量团体中的所有点都能够当选。

注意:从样例中可以得到一个人可以同时支持多个人,且支持的人都能得到他的全部票数

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 #include<set>
  7 using namespace std;
  8 const int maxn=20010;
  9 const int maxm=50010;
 10 struct edge{
 11     int to,nxt;
 12 }edge[maxm];
 13 int head[maxn],tot;
 14 int low[maxn],dfn[maxn],stack[maxn],belong[maxn],cnt[maxn];
 15 int index,top;
 16 int scc;
 17 bool vis[maxn],vis_[maxn];
 18 int num[maxn],in[maxn],out[maxn];
 19 vector<int>G[maxn];
 20
 21 void addedge(int u,int v)
 22 {
 23     edge[tot].to=v;
 24     edge[tot].nxt=head[u];
 25     head[u]=tot++;
 26 }
 27
 28 void addedge_(int u,int v)
 29 {
 30     G[u].push_back(v);
 31 }
 32
 33 void tarjan(int u)
 34 {
 35     int v;
 36     low[u]=dfn[u]=++index;
 37     stack[top++]=u;
 38     vis[u]=true;
 39     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
 40         v=edge[i].to;
 41         if ( !dfn[v] ) {
 42             tarjan(v);
 43             low[u]=min(low[u],low[v]);
 44         }
 45         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
 46     }
 47     if ( low[u]==dfn[u] ) {
 48         scc++;
 49         do {
 50             v=stack[--top];
 51             vis[v]=false;
 52             belong[v]=scc;
 53             num[scc]++;
 54         }
 55         while ( v!=u );
 56     }
 57 }
 58
 59 void solve(int N)
 60 {
 61     memset(dfn,0,sizeof(dfn));
 62     memset(vis,false,sizeof(vis));
 63     memset(num,0,sizeof(num));
 64     index=scc=top=0;
 65     for ( int i=1;i<=N;i++ ) {
 66         if ( !dfn[i] ) tarjan(i);
 67     }
 68 }
 69
 70 void init()
 71 {
 72     tot=0;
 73     memset(head,-1,sizeof(head));
 74 }
 75
 76 int BFS(int u)
 77 {
 78     memset(vis,false,sizeof(vis));
 79     queue<int>que;
 80     que.push(u);
 81     vis[u]=true;
 82     int now=num[u];
 83     while ( !que.empty() ) {
 84         int v=que.front();
 85         que.pop();
 86         for ( int i=0;i<G[v].size();i++ ) {
 87             int j=G[v][i];
 88             if ( !vis[j] ) {
 89                 vis[j]=true;
 90                 que.push(j);
 91                 now+=num[j];
 92             }
 93         }
 94     }
 95     return now;
 96 }
 97
 98 int main()
 99 {
100     int T,i,j,k,h,x,y,z,n,m,ans,now,cnt_;
101     scanf("%d",&T);
102     for ( h=1;h<=T;h++ ) {
103         scanf("%d%d",&n,&m);
104         init();
105         for ( i=1;i<=n;i++ ) G[i].clear();
106         for ( i=1;i<=m;i++ ) {
107             scanf("%d%d",&x,&y);
108             x++;y++;
109             addedge(x,y);
110         }
111         solve(n);
112         memset(in,0,sizeof(in));
113         memset(out,0,sizeof(out));
114         memset(cnt,0,sizeof(cnt));
115         memset(vis_,false,sizeof(vis_));
116         for ( i=1;i<=n;i++ ) {
117             for ( j=head[i];j!=-1;j=edge[j].nxt ) {
118                 int v=edge[j].to;
119                 if ( belong[v]!=belong[i] ) {
120                     in[belong[v]]++;
121                     out[belong[i]]++;
122                     addedge_(belong[v],belong[i]);
123                 }
124             }
125         }
126         ans=0;
127         k=0;
128         for ( i=1;i<=scc;i++ ) {
129             if ( out[i]==0 ) {
130                 cnt[i]=BFS(i);
131                 if ( cnt[i]>ans ) ans=cnt[i];
132             }
133         }
134         for ( i=1;i<=scc;i++ ) {
135             if ( cnt[i]==ans ) {
136                 vis_[i]=true;
137                 k+=num[i];
138             }
139         }
140         printf("Case %d: %d\n",h,ans-1);
141         cnt_=0;
142         for ( i=1;i<=n;i++ ) {
143             if ( vis_[belong[i]] ) {
144                 printf("%d",i-1);
145                 if ( ++cnt_==k ) {
146                     printf("\n");
147                     break;
148                 }
149                 else printf(" ");
150             }
151         }
152     }
153     return 0;
154 }

HDOJ3639

5.(HDOJ3072)http://acm.hdu.edu.cn/showproblem.php?pid=3072

题意:

分析:tarjan+类最小生成树

6.(HDOJ3861)http://acm.hdu.edu.cn/showproblem.php?pid=3861

题意:有一个国王,有n个城市和m条路径。先将国王分成几个地区,地区满足:若城市u能到城市v同时城市v能到城市u,则它们必定属于一个地区。于此同时还有其他点也可以属于该地区,即一个地区的两点u,v一定存在一条不经过其他地区的从u到v或者从v到u的线路。

分析:tarjan+最小路径覆盖。先用tarjan进行缩点,在新图的基础上构建二分图匹配求出最大匹配进而得到最小路径数。注意点数较多,所有二分匹配用邻接表而不是临界矩阵存。同时点数好像比所给的范围要大的多

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 using namespace std;
  6 const int maxn=20010;
  7 const int maxm=100010;
  8 struct edge{
  9     int to,nxt,val;
 10 }edge[maxm];
 11 int head[maxn],tot;
 12 int low[maxn],dfn[maxn],stack[maxn],belong[maxn],girl[maxn];
 13 int index,top;
 14 int scc,n;
 15 bool vis[maxn];
 16 vector<int>G[maxn];
 17
 18 void addedge(int u,int v)
 19 {
 20     edge[tot].to=v;
 21     edge[tot].nxt=head[u];
 22     head[u]=tot++;
 23 }
 24
 25 void tarjan(int u)
 26 {
 27     int v;
 28     low[u]=dfn[u]=++index;
 29     stack[top++]=u;
 30     vis[u]=true;
 31     for ( int i=head[u];i!=-1;i=edge[i].nxt ) {
 32         v=edge[i].to;
 33         if ( !dfn[v] ) {
 34             tarjan(v);
 35             low[u]=min(low[u],low[v]);
 36         }
 37         else if ( vis[v] ) low[u]=min(low[u],dfn[v]);
 38     }
 39     if ( low[u]==dfn[u] ) {
 40         scc++;
 41         do {
 42             v=stack[--top];
 43             vis[v]=false;
 44             belong[v]=scc;
 45         }
 46         while ( v!=u );
 47     }
 48 }
 49
 50 void solve()
 51 {
 52     memset(dfn,0,sizeof(dfn));
 53     memset(vis,false,sizeof(vis));
 54     index=scc=top=0;
 55     for ( int i=1;i<=n;i++ ) {
 56         if ( !dfn[i] ) tarjan(i);
 57     }
 58 }
 59
 60 void init()
 61 {
 62     tot=0;
 63     memset(head,-1,sizeof(head));
 64 }
 65
 66 bool find(int x)
 67 {
 68     int i,j;
 69     for ( i=0;i<G[x].size();i++ ) {
 70         j=G[x][i];
 71         if (  vis[j]==false ) {
 72             vis[j]=true;
 73             if ( girl[j]==0 || find(girl[j]) ) {
 74                 girl[j]=x;
 75                 return true;
 76             }
 77         }
 78     }
 79     return false;
 80 }
 81
 82 int main()
 83 {
 84     int m,i,j,k,x,y,z,ans,T;
 85     scanf("%d",&T);
 86     while ( T-- ) {
 87         scanf("%d%d",&n,&m);
 88         init();
 89         while ( m-- ) {
 90             scanf("%d%d",&x,&y);
 91             addedge(x,y);
 92         }
 93         solve();
 94         for ( i=1;i<=scc;i++ ) G[i].clear();
 95         for ( i=1;i<=n;i++ ) {
 96             for ( j=head[i];j!=-1;j=edge[j].nxt ) {
 97                 int v=edge[j].to;
 98                 x=belong[i];
 99                 y=belong[v];
100                 if ( x!=y )    G[x].push_back(y);
101             }
102         }
103         ans=0;
104         memset(girl,0,sizeof(girl));
105         for ( i=1;i<=scc;i++ ) {
106             memset(vis,false,sizeof(vis));
107             if ( find(i) ) ans++;
108         }
109         ans=scc-ans;
110         printf("%d\n",ans);
111     }
112     return 0;
113 }

HDOJ3861

7.(HDOJ2242)http://acm.hdu.edu.cn/showproblem.php?pid=2242

原文地址:https://www.cnblogs.com/HDUjackyan/p/8758864.html

时间: 2024-10-20 06:30:19

专题训练之强连通分量和2-sat的相关文章

面试专题训练之“双指针”

一.需要思考的问题包括以下几点: 双指针是什么,什么时候需要用到双指针 通用的模板是什么 实现过程中需要注意的细节有哪些 常见的双指针题型有哪些 二.模板整理 三.专题训练 1.Leetcode283 1 class Solution { 2 public: 3 void moveZeroes(vector<int>& nums) { 4 int n = nums.size(); 5 int j = 0; 6 for (int i = 0; i < n; i++) { 7 if

模拟专题训练小结

本周我进行了针对模拟题的训练,在比赛中,模拟题是考察一个人代码综合能力的最佳体现,也是考验选手对细节的把握能力的有力工具.本周的模拟题大多来自WF和Regional,而前者的模拟题一般细节比较多,编程比较复杂.下面来根据我本周的训练情况来简要总结一下这方面需要注意的地方. 首先,应该完全理解题意,这一步相当关键,如果连题意都理解错了,那么后面无论花多大功夫去调试代码都是无济于事,因为你一直在实现一个错误的模拟过程.弄明白题目的全部流程,接下来就是考虑顶层设计:有哪些全局变量,需要设计哪些结构体,

专题训练8总结

这个专题主要学了两个数据结构 一个是线段树 一个是树状数组 线段树主要求区域操作 建树.单点查询.单点修改.区间查询.区间修改. 代码较为复杂 参考模板 树状数组  用于求和效率很高 进阶则为区域修改同一个值十分方便 主要有两种操作: 单点修改 区域查询(基础)  区域查询的差值即为单点查询   也比枚举算法快很多 区域修改  单点查询 (进阶) 1.敌兵布阵 线段树入门题   但是采用树状数组十分方便 很简单没什么好说的 2.Color the ball 一开始用线段树   debug一个me

UESTC 电子科大专题训练 数据结构 D

UESTC 1584 题意:平面坐标上有n个怪物,每个怪物有一个rank值,代表x坐标和y坐标都不大于它本身的怪物数(不包括本身) 思路:对x y坐标从小到大排序,x优先排序,用数状数组计算y坐标小于它的数量 AC代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #i

UESTC 电子科大专题训练 数据结构 A

UESTC 1591 题意:求区间极值之差 思路:线段树裸题,不带更新 ACA代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "ma

二分暑假专题 训练记录 2017-7-29

POJ3258-River Hopscotch 题意: 给你区间[0,L]给你n个石头,然后去除m个石头  最大化 石头间最小的距离 思路: 首先0和L 这两个石头是不可以动的   然后用 s 数组记录 整个区间的石头 然后排序  此时石头的排序就是有序的了  然后二分套模板 接着check函数才是最关键的好的把 从0到 n+1-m   总共就有 n+2-m 个石头了 而由于第0个石头不可以动 , 所以从第一个开始动 同时判断条件是 s[cur] - s[last] < d 而不是 <= #i

UESTC 电子科大专题训练 数论 L

UESTC 1723 题意:中文题 思路:预处理,dp[i][j]表示将j个人放到i个房间里,则可以得到dp[i][j]=dp[i][j-1]*i + dp[i-1][j-1],递推式的理解,第一:当有i个房间,j-1个人的时候方案数已知为dp[i][j-1],则当增加一个人的时候,第j个人可以选择i个房间的任意一个,或者选择一个新的房间,但是只有选择已有的i个房间才能递推得dp[i][j],第二:当有i-1个房间,j-1个人时,增加一个人,这个人有i+1种选择(i种选择为选择已有的房间,第i+

UESTC 电子科大专题训练 数据结构 J

UESTC 1599 题意:中文题..不写了 思路:优先对列,小的优先 AC代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map

UESTC 电子科大专题训练 数论 G

UESTC 1718 题意:在01串中选出长度为偶数,并且前一半是0,后一半是1的子序列方案数 思路:组合数+范德蒙恒等式 记录每个数前面0的个数pi和后面1的个数nexi(包括本身)遍历到第k个数的时候,如果是0 那么方案数为(因为计算第i位时,前面计算的i-1个答案都不包含这一位,但是第i位计算的答案都包含第i位 所以没有重复) for(i=0, -> i=min(pi-1,nexi)) C(pi-1,i)*C(nexi,i+1) 可以由 C(l-1,i)=C(l,i+1)-C(l-1,i+