Codeforces Round #375 (Div. 2) Analyses
神他喵难的一场cf
A.The New Year: Meeting Friends
Problems:三个人要走到一个地方,给定x1,x2,x3,问最小代价。
Analysis:思维题,讨论一下就知道答案为max({x1, x2, x3})-min({x1, x2, x3})
Tags:Math, Sorting
Problems:给定一串字符串,只会出现字母,_以及左右括号,问括号外最长的单词长度以及括号内有几个单词
Analysis:一开始以为括号可以嵌套,感觉巨烦,然而,简单模拟
Tags:Implementation
Problems:题面神他喵的烦,其实就是给定一串序列,让你将其修改,使得1-m数目最小的出现次数最大,且修改次数最小
Analysis:首先出现次数的答案是固定的,即n/m(平均分配)。接下去就是分配的问题了,对于那些>m的数,如果存在一个数小于min(m,n/m),那么就直接修改,否则就不动。之后寻找是否有出现次数<n/m的数,将那些出现次数>n/m的数修改过去就好了
Tags:Greedy
#include<cstdio>
#include<cstring>
#include<algorithm>
//#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define INF 2000000000
#define Clear(x, Num) memset(x, Num, sizeof(x))
#define Low(x) ((x>='a') && (x<='z'))
#define Cap(x) ((x>='A') && (x<='Z'))
#define Dig(x) ((x>='0') && (x<='9'))
#define Neg(x) (x=='-')
#define G_c() getchar()
typedef long long ll;
int n, m, a[2010], Cnt[2010], Change;
inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
//inline void Insert(int u, int v, int w) { To[Cnt]=v; Id[Cnt]=w; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
int main()
{
read(n); read(m);
for (int i=1; i<=n; i++)
{
read(a[i]);
if (a[i]<=m) Cnt[a[i]]++;
}
for (int i=1; i<=m; i++)
{
int More=(Cnt[i]<(n/m))?(n/m-Cnt[i]):0;
if (More)
for (int j=1; j<=n; j++)
if ((a[j]>m) || (Cnt[a[j]]>n/m))
{
if (a[j]<=m) Cnt[a[j]]--;
a[j]=i; Change++; More--;
if (!More) break;
}
}
printf("%d %d\n", n/m, Change);
for (int i=1; i<=n; i++) printf("%d ", a[i]); puts("");
}
Problems:给你一个地图,其中"*"为sand,"."为lake,一个湖的定义为不和边界有交点并被沙子包围,填湖的代价为湖的面积,求湖的个数<=k的最小代价
Analysis:这题反而水了,直接dfs出湖,sort一下贪心就可以了。
Tags:Greedy, Dfs and similar
#include<cstdio>
#include<cstring>
#include<algorithm>
//#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define INF 2000000000
#define Clear(x, Num) memset(x, Num, sizeof(x))
#define Low(x) ((x>='a') && (x<='z'))
#define Cap(x) ((x>='A') && (x<='Z'))
#define Dig(x) ((x>='0') && (x<='9'))
#define Neg(x) (x=='-')
#define G_c() getchar()
typedef long long ll;
struct Data
{
int x, y, Area;
}Lake[10010];
int n, m, k, Map[110][110], Ans, Cnt, Ant;
bool flag;
inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
//inline void Insert(int u, int v, int w) { To[Cnt]=v; Id[Cnt]=w; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
inline bool Cmp(const Data &a, const Data &b) { return a.Area<b.Area; }
inline int dfs(int _x, int _y, int Color)
{
if ((_x<1) || (_x>n) || (_y<1) || (_y>m) || (Map[_x][_y]==Color) || (!Map[_x][_y])) return 0;
if ((_x==1) || (_x==n) || (_y==1) || (_y==m)) { flag=1; return 0; }
Map[_x][_y]=Color;
return dfs(_x-1, _y, Color)+dfs(_x+1, _y, Color)+dfs(_x, _y-1, Color)+dfs(_x, _y+1, Color)+1;
}
int main()
{
scanf("%d%d%d", &n, &m, &k); char x=G_c();
for (int i=1; i<=n; i++)
{
for (int j=1; j<=m; j++)
{
x=G_c();
if (x=='.') Map[i][j]=-1;
}
x=G_c();
}
/*for (int i=1; i<=n; i++)
{ for (int j=1; j<=m; j++) printf("%d ", Map[i][j]); puts(""); }*/
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
if (Map[i][j]==-1)
{
flag=0; int Area=dfs(i, j, ++Cnt);
if (!flag) Lake[Cnt].x=i, Lake[Cnt].y=j, Lake[Cnt].Area=Area;
else Cnt--;
}
sort(Lake+1, Lake+Cnt+1, Cmp);
for (int i=1; i<=Cnt-k; i++) Ans+=Lake[i].Area, dfs(Lake[i].x, Lake[i].y, 0);
printf("%d\n", Ans);
for (int i=1; i<=n; i++)
{
for (int j=1; j<=m; j++) if (Map[i][j]) printf("."); else printf("*");
puts("");
}
}
Problems:将一个无向图修改,使得入度==出度的点数尽可能的多,并输出方案
Analysis:首先度数为奇的点必然不是答案,那么Res=n-度数为奇的点,再考虑这些点,每次选择从一个点出发进行修改一条路径(直到另一个奇点),经过的点都走偶数次,直到该点度数为0,即可
Tags:Greedy, Dfs and similar, Graphs
#include<cstdio>
#include<cstring>
#include<algorithm>
//#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define INF 2000000000
#define Clear(x, Num) memset(x, Num, sizeof(x))
#define Dig(x) ((x>='0') && (x<='9'))
#define Neg(x) (x=='-')
#define G_c() getchar()
typedef long long ll;
struct Data
{
int x, y;
}Edge[40010];
int T, n, m, x, y, Edge_Cnt, Res, In[2010];
int G[2010][2010];
inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
//inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
inline void dfs(int u)
{
while (In[u])
{
for (int i=1; i<=n; i++)
if (G[u][i])
{
int v=i;
Edge[++Edge_Cnt].x=u, Edge[Edge_Cnt].y=v;
In[u]--, In[v]--; G[u][v]=G[v][u]=0;
u=v;
break;
}
}
}
int main()
{
read(T);
while (T--)
{
read(n); read(m);
Edge_Cnt=0; Res=n;
for (int i=1; i<=n; i++) { In[i]=0; for (int j=1; j<=n; j++) G[i][j]=0; }
for (int i=1; i<=m; i++)
{
read(x), read(y);
G[x][y]=G[y][x]=1;
In[x]++, In[y]++;
}
for (int i=1; i<=n; i++) Res-=(In[i]&1);
printf("%d\n", Res);
for (int i=1; i<=n; i++)
if (In[i]&1) while (In[i]) dfs(i);
for (int i=1; i<=n; i++) while (In[i]) dfs(i);
for (int i=1; i<=Edge_Cnt; i++) printf("%d %d\n", Edge[i].x, Edge[i].y);
}
}
Problems:给你一张图,求一颗生成树,使得源点s度数不超过ds,汇点t度数不超过dt,并按照输入顺序输出
Analysis:先考虑和s,t无关的点集,每个点集只有三种连法
1. 和s和t均相连:标记
2. 和s或者t中的一个相连:直接和另一个点相连。
3. 孤立点:无法构成要求的生成树
对于这些标记点集,若不和s和t联通,则考虑是否可以将s和t相连,若不可以,则无法构成要求的生成树
剩下的点只需要考虑s或者t相连即可
Tags:Greedy, Dsu, Graphs
#include<cstdio>
#include<cstring>
#include<algorithm>
//#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define INF 2000000000
#define Clear(x, Num) memset(x, Num, sizeof(x))
#define Dig(x) ((x>='0') && (x<='9'))
#define Neg(x) (x=='-')
#define G_c() getchar()
#define Maxn 200010
#define Maxe 800010
typedef long long ll;
vector<int >Point[Maxn];
int n, m, x[Maxe], y[Maxe], To[Maxe], Next[Maxe], Id[Maxe], Head[Maxn], Cnt;
int source, sink, dep_s, dep_t;
int f[Maxn], Ans_s[Maxn], Ans_t[Maxn], Cnt_s, Cnt_t;
bool Used[Maxe];
inline int Get_f(int x) { return (x==f[x])?(x):(f[x]=Get_f(f[x])); }
inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); }
inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; }
inline void Insert(int u, int v, int w) { To[Cnt]=v; Id[Cnt]=w; Next[Cnt]=Head[u]; Head[u]=Cnt++; }
int main()
{
read(n); read(m); for (int i=1; i<=n; i++) Head[i]=-1; Cnt=0;
for (int i=1; i<=m; i++)
{
read(x[i]); read(y[i]);
Insert(x[i], y[i], i), Insert(y[i], x[i], i);
}
read(source); read(sink); read(dep_s); read(dep_t);
for (int i=1; i<=n; i++) f[i]=i;
for (int u=1; u<=n; u++)
if ((u^source) && (u^sink))
for (int p=Head[u]; p!=-1; p=Next[p])
{
int v=To[p]; if ((v==source) || (v==sink)) continue;
int Anc_u=Get_f(u), Anc_v=Get_f(v);
if (Anc_u^Anc_v) Used[Id[p]]=1, f[Anc_u]=Anc_v;
}
for (int i=1; i<=n; i++) Point[Get_f(i)].push_back(i);
for (int u=1; u<=n; u++)
if ((u^source) && (u^sink) && (f[u]==u))
{
int Link_source=0, Link_sink=0;
for (int p=0; p<Point[f[u]].size(); p++)
{
int v=Point[u][p];
if (f[v]==u)
{
for (int _p=Head[v]; _p!=-1; _p=Next[_p])
{
int _v=To[_p];
if (_v==source) Link_source=Id[_p]; else if (_v==sink) Link_sink=Id[_p];
}
if ((Link_source) && (Link_sink)) break;
}
}
if ((!Link_source) && (!Link_sink)) { puts("No"); return 0; }
if ((Link_source) && (Link_sink)) Ans_s[++Cnt_s]=Link_source, Ans_t[++Cnt_t]=Link_sink;
else
{
if (Link_source) dep_s--, f[u]=source, Used[Link_source]=1;
if (Link_sink) dep_t--, f[u]=sink, Used[Link_sink]=1;
}
}
if (Cnt_s) dep_s--, dep_t--, Used[Ans_s[1]]=1, Used[Ans_t[1]]=1;
else
{
int Anc=Get_f(1);
for (int i=1; i<=n; i++) if (Get_f(i)^Anc) { Anc=-1; break; }
if (Anc==-1)
{
bool flag=0;
for (int p=Head[source]; p!=-1; p=Next[p])
{
int v=To[p];
if (v==sink) { flag=1; Used[Id[p]]=1; break; }
}
if (!flag) { puts("No"); return 0; }
dep_s--; dep_t--;
f[source]=sink;
}
}
for (int i=2; i<=Cnt_s; i++)
{
if (dep_s) { dep_s--, Used[Ans_s[i]]=1; continue; }
dep_t--, Used[Ans_t[i]]=1;
}
if ((dep_s<0) || (dep_t<0)) { puts("No"); return 0; }
puts("Yes");
for (int i=1; i<=m; i++) if (Used[i]) printf("%d %d\n", x[i], y[i]);
}