您的位置:首页 > 其它

【2018年全国多校算法寒假训练营练习比赛(第四场)】ABCDEFGH

2018-02-11 19:18 746 查看

A石油采集

分析:二分匹配。

一个油田只能够和一个油田匹配被瓢走 ,所以我们 对每一个油田 遍历其四周,如果也有油田,那么就建立边表示有可能匹配。 最后匈牙利算法求最大匹配就好了。

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 50*50+11;
const int M = 1E6+11;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const LL inff = 0x3f3f3f3f3f3f3f3f;

int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch<='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
/*-------------------------*/
struct Edge {
int from,to,next;
}edge[M];
int head
,top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b){
Edge e={a,b,head[a]};
edge[top]=e; head[a]=top++;
}
int used
,pipei
;
bool Find(int x){
for(int i=head[x];i!=-1;i=edge[i].next){
Edge e=edge[i];
if(!used[e.to]){
used[e.to]=1;
if(pipei[e.to]==-1 || Find(pipei[e.to])){
pipei[e.to]=x;

return true;
}
}
}
return false;
}
int  to[4][2]={0,1,0,-1,1,0,-1,0};
bool mp

;
int  solve(int n){
memset(pipei,-1,sizeof(pipei));
int ans=0;
for(int i=1;i<=n*n;i++){
memset(used,0,sizeof(used));
if(Find(i) ) ans++;
}
return ans;
}

int main(){
int T;scanf("%d",&T);int zz=1;
while(T--){
init();
memset(mp,0,sizeof(mp));
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
string s;cin>>s;
for(int j=0;j<n;j++){
if(s[j]=='#') mp[i][j+1]=true;
else mp[i][j+1]=false;
}
}

/* for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%d",mp[i][j]);
}
puts("");
}*/

for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!mp[i][j]) continue;
for(int k=0;k<4;k++){
int nx=i+to[k][0]; int ny=j+to[k][1];
if(mp[nx][ny])
addedge((i-1)*n+j,(nx-1)*n+ny);
//  mp[nx][ny]=false ;
}
}
}
printf("Case %d: %d\n",zz++,solve(n)/2); // 重复
}
return 0;
}

/*

2
6
......
.##...
......
.#..#.
.#..##
......
4
###.
#...
.###
..#.

*/


B道路建设

分析:最小生成树模板题

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 1e5 +11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/
struct Edge{
int from,to,val;
}edge[M];
bool cmp(Edge a,Edge b){
return a.val<b.val;
}
int pre
;

void init(int n){
for(int i=0;i<=n;i++) pre[i]=i;
}
int Find(int x){
return x==pre[x]?x:(pre[x]=Find(pre[x]));
}
void Join(int x,int y){
x=Find(x);y=Find(y);
if(x!=y) pre[x]=y;
}
int main(){
int c,n,m;
while(scanf("%d%d%d",&c,&n,&m)!=EOF){
init(m);
for(int i=0;i<n;i++)
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val);
sort(edge,edge+n,cmp);

int ans=0; int flag=1;
for(int i=0;i<n;i++){
Edge e=edge[i];
if(Find(e.to)!=Find(e.from)){
Join(e.to,e.from);
ans+=e.val;
}
}
if(ans<=c) puts("Yes") ;
else puts("No");
}
return 0;
}

/*
链接:https://www.nowcoder.net/acm/contest/76/B
来源:牛客网

20 10 5
1 2 6
1 3 3
1 4 4
1 5 5
2 3 7
2 4 7
2 5 8
3 4 6
3 5 9
4 5 2

10 2 2
1 2 5
1 2 15
*/


C求交集

分析:二分查找。

我用map MLE了..QAQ

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 2e6 +11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/
int a
;
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int have=0;
for(int i=0;i<m;i++){
int c;scanf("%d",&c);
int pos=lower_bound(a,a+n,c)-a;
if(a[pos]==c) {
if(have++) putchar(' ');
printf("%d",c);
}
}
if(!have) puts("empty");
else puts("");
}
return 0;
}


D 小明的挖矿之旅

分析: 因为每个点只能够右和下移动,所以整个图就相当于一个DAG图。然后讨论入度为0 和出度为0的个数就行了

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 1000*1000 +11;
const int M = 1000+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/

//vector<int>ve
;
int in
,out
;
void init(int n){
for(int i=0;i<n;i++) {
// ve[i].clear();
out[i]=in[i]=0;
}
}
void addedge(int a,int b){
// ve[a].push_back(b);
in[b]++; out[a]++;
}
bool mp[M][M];
void show(int n,int m){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d",mp[i][j]);
}
puts("");
}
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
init(n*m);memset(mp,0,sizeof(mp));
for(int i=0;i<n;i++){
string s;cin>>s;
for(int j=0;j<m;j++){
if(s[j]=='.') mp[i+1][j+1]=true;
else mp[i+1][j+1]=false;
}
}
// show(n,m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]){
int nx=i+1;int ny=j;
if(mp[nx][ny]) addedge((i-1)*m+j-1,(nx-1)*m+ny-1);
nx=i;ny=j+1;
if(mp[nx][ny]) addedge((i-1)*m+j-1,(nx-1)*m+ny-1);
}
}
}
int a,b,c;
a=b=c=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]){
if(in[(i-1)*m+j-1]==0) a++;
if(out[(i-1)*m+j-1]==0) b++;
c++;
}
}
}
if(c==0) puts("0");
else if(a==c&&b==c) printf("%d\n",a-1);
else printf("%d\n",max(a,b));
}
return 0;
}


E 通知小弟

分析:scc+缩点 ,求缩点后的入度 ,如果入度为0且HA能够通知到的间谍 不在这个缩点里的话,肯定是-1 ,否则就是入度为0的点的个数。

只要入度为0的被通知了,那么入度不为的点肯定会由入度为0的传过来。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 1000 +11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/
struct Edge{
int from,to,nexts;
}edge[M];
int head
,top;
int n,m;
void init(){
memset(head,-1,sizeof(head)) ;
top=0;
}
void addedge(int a,int b){
Edge e={a,b,head[a]} ;
edge[top]=e;head[a]=top++;
}
int dfn
,low
;
int sccno
,scc_cnt;
stack<int>S; bool Instack
;
vector<int>scc
;
int mp

;
int dfs_clock;
void tarjan(int now){
low[now]=dfn[now]=++dfs_clock;
S.push(now);Instack[now]=1;
for(int i=head[now];i!=-1;i=edge[i].nexts){
Edge e=edge[i];
if(!dfn[e.to]){
tarjan(e.to);
low[now]=min(low[now],low[e.to]);
}else if(Instack[e.to])
low[now]=min(low[now],dfn[e.to]);
}
if(dfn[now]==low[now]){
scc_cnt++;scc[scc_cnt].clear();
for(;;){
int nexts=S.top();S.pop();Instack[nexts]=0;
sccno[nexts]=scc_cnt;
scc[scc_cnt].push_back(nexts);
if(nexts==now) break;
}
}
}
void find_cut(int le,int ri){
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(Instack,0,sizeof(Instack));
memset(sccno,0,sizeof(sccno));
dfs_clock=scc_cnt=0;
for(int i=le;i<=ri;i++)
if(!dfn[i]) tarjan(i);
}
int in
;
void suodian(){  // 建立DAG图
for(int i=1;i<=scc_cnt;i++)
memset(mp[i],0,sizeof(mp[i]));
for(int i=1;i<=scc_cnt;i++) in[i]=0;
for(int i=0;i<top;i++){
Edge e=edge[i];
int now=sccno[e.from];
int nexts=sccno[e.to];
if(now!=nexts){
in[nexts]++;
mp[now][nexts]=1;
}
}
}
int HA
;
map<int,int>zzx;
int main(){
int mm;
while(scanf("%d%d",&n,&mm)!=EOF){
init(); zzx.clear();
for(int i=1;i<=mm;i++) scanf("%d",&HA[i]);
for(int i=1;i<=n;i++){
int num=0; scanf("%d",&num);
for(int j=1;j<=num;j++){
int zz; scanf("%d",&zz);
addedge(i,zz);
}
}
find_cut(1,n);
suodian();
//cout<<scc_cnt<<endl;
for(int i=1;i<=mm;i++) zzx[sccno[HA[i]]]=1;
int flag=1; int ans=0;
for(int i=1;i<=scc_cnt;i++){
if(in[i]==0){
if(zzx[i]==0) flag=0;  // HA通知到的间谍有没有这个在这里联通快中
ans++;
}
}
if(!flag) puts("-1");
else printf("%d\n",ans);
}
return 0;
}


F Call to your teacher

分析:floyd 求传递闭包 模板题

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 100 +11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/

int mp

;
int n,m;
void wall(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++){
mp[i][j]=mp[i][j]|(mp[i][k]&mp[k][j]);
}
}
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
memset(mp,0,sizeof(mp));
while(m--){
int a,b;scanf("%d%d",&a,&b);
mp[a][b]=1;
}
wall();
if(mp[1]
) puts("Yes");
else puts("No");
}
return 0;
}


G 老子的意大利炮呢

分析: 状态压缩 + 优先队列的BFS

不难,但是太菜了,没时间写了。

三种物品,可以用状态压缩来表示当前拥有的状态 。

1<<1 表示拥有第一件物品,1<<2表示拥有第二件物品 ,1<<3表示拥有第三件物品.

然后 就是针对每种情况逐个分析就行了 ,这里一定要思路清晰,不然很容易错。

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 100+11;
const int M = 1E6+11;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const LL inff = 0x3f3f3f3f3f3f3f3f;

int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch<='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
/*-------------------------*/

struct Node {
int x,y,step,state;
bool operator<(const Node &b)const {
return step>b.step;
}
};
int mp

,speed[1<<5];
int vis

[1<<5];
int to[4][2]={1,0,0,1,-1,0,0,-1};
void Cal(int &cnt,int &tt,Node now){
cnt=0; tt=1;
for(int i=1;i<=3;i++){
if((1<<i)&now.state){
cnt++; tt+=speed[1<<i];
}
}
}
void bfs(Node st){
memset(vis,0,sizeof(vis));
priority_queue<Node>Q;
Q.push(st); vis[st.x][st.y][st.state]=1;
while(!Q.empty()){
Node now=Q.top(); Q.pop();
for(int i=0;i<4;i++){
int nx=now.x+to[i][1]; int ny=now.y+to[i][0];
if(mp[nx][ny]==0 || vis[nx][ny][now.state]) continue;  //对所有的情况逐个分析   关键

if(mp[nx][ny]==6){
int cnt,tt; Cal(cnt,tt,now);
if(cnt!=3){
Node next={nx,ny,now.step+tt,now.state};
vis[nx][ny][next.state]=1;
Q.push(next);
}
continue;
}
if(mp[nx][ny]==5){
int cnt,tt;  Cal(cnt,tt,now);
if(cnt==3) {
//printf("%d \n",tt);
printf("%d\n",now.step+tt);
return ;
}

continue;
}
if(mp[nx][ny]==1) {
int cnt,tt; Cal(cnt,tt,now);
Node ne={nx,ny,now.step+tt,now.state};
vis[nx][ny][ne.state]=1; Q.push(ne);
continue;
}
if(mp[nx][ny]>=2&&mp[nx][ny]<=4){
int cnt,tt;  Cal(cnt,tt,now);

Node ne={nx,ny,now.step+tt,now.state | (1<<(mp[nx][ny]-1))};
vis[nx][ny][ne.state]=1; Q.push(ne);

Node next={nx,ny,now.step+tt,now.state};
vis[nx][ny][next.state]=1;  Q.push(next);
continue;
}
}
}
puts("-1");
}

void show(int n,int m){ //debug
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) {
printf("%d",mp[i][j]);
}
puts("");
}
}

int main(){
memset(mp,0,sizeof(mp));
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
string s;cin>>s;
for(int j=0;j<m;j++){
if(s[j]=='#') mp[i][j+1]=6;
else mp[i][j+1]=1;
}
}

Node st;
for(int i=1;i<=5;i++){
int x,y;scanf("%d%d",&x,&y);
if(i==1) { st.x=x;st.y=y;st.step=0;st.state=0; }
mp[x][y]=i;
}
// show(n,m);
speed[0]=1;
for(int i=1;i<=3;i++){
int t;scanf("%d",&t);
speed[1<<i]=t;
}
// for(int i=1;i<=3;i++) printf("%d ",speed[1<<i]);

bfs(st);
return 0;
}

/*

3 5
##.##
.#.#.
##.##
1 3 2 1 2 3 2 5 3 3
1 5 4

*/


H 老子的全排列呢

分析:直接调用函数 。

代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long

const int N = 500 +11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
const LL  inff= 0x3f3f3f3f3f3f3f3f ;
const int mod = 1e9+7;
const double PI = acos(-1.0);

int read(){
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=(x<<1)+ (x<<3)+ch-'0' ; ch=getchar();}
return x*f;
}
/*----------------------------------*/

int a[8]={1,2,3,4,5,6,7,8};
int main(){
do{
for(int i=0;i<8;i++) printf("%d%s",a[i],i==7?"":" ");
puts("");
}while(next_permutation(a,a+8));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐