赛前翻车真酸爽,还有几天就哈尔滨站了,居然搞成这样子。
训练赛的整个节奏被卡在一个D题,题目出发点搞错了,WA 31之后觉得思路没问题但思路就是有问题。
D:Problem D Denouncing Mafia
题目大意:一棵树找k条链使得总点数最多。
起初想的是,只要摘下 叶子数-k个小链就可以,但是不知道那出错了,正解的思路是,预处理出每条链被删掉之后,形成的森林集合,再从集合中选择最长的。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1e5+4;
vector<int>v[MAXN],s[MAXN];
int maxx[MAXN];
struct node
{
int v,val;
node(){}
node(int a,int b){
v = a;val = b;
}
bool operator < (const node & r)const{
return val<r.val;
}
};
void dfs(int x)
{
maxx[x] = 1;
int vv=0,Max = 0;
int len = v[x].size();
for(int i=0;i<len;i++){
int to = v[x][i];
dfs(to);
if(maxx[to] + 1 >= maxx[x]){
maxx[x] = maxx[to] + 1;
vv = to;
}
}
// cout<<x<<" * "<<vv<<endl;
for(int i=0;i<len;i++){
int to = v[x][i];
if(to!=vv){
s[x].push_back(to);
//cout<<x<<" <-- "<<to<<endl;
}
else{
int len2 = s[to].size();
for(int j=0;j<len2;j++){
int tt = s[to][j];
s[x].push_back(tt);
//cout<<x<<" + "<<tt<<" - "<<to<<endl;
}
}
}
}
priority_queue<node>q;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=2;i<=n;i++){
int x;
scanf("%d",&x);
v[x].push_back(i);
}
dfs(1);
q.push(node(1,maxx[1]));
// for(int i=1;i<=n;i++){
// int len = s[i].size();
// cout<<i<<" : ";
// for(int j=0;j<len;j++){
// cout<<s[i][j]<<" ";
// }
// cout<<endl;
// }
// cout<<endl;
int ans = 0;
while(k--)
{
node now = q.top();
q.pop();
ans += now.val;
int len = s[now.v].size();
for(int i=0;i<len;i++){
int to = s[now.v][i];
q.push(node(to,maxx[to]));
}
}
printf("%d\n",ans);
}
J . Problem J Jar of Water Game
题目大意:很无脑的模拟,也不算很大,比赛期间题目都没有读,至少比D题简单很多。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,k,w,now;
char C[100][10];
vector<char>v[50];
bool vis[50];
int num[20];
int id[500];
bool is_win(int x)
{
if(w!=x && v[x].size() == 4 && v[x][0] == v[x][1] && v[x][1] == v[x][2] && v[x][2] == v[x][3])return 1;
else return 0;
}
bool cmp(char x,char y)
{
if(num[ id[x] ] == num[ id[y] ] ){
return id[x] < id[y];
}
return num[ id [x] ] < num[ id[y] ];
}
char ask(int x)
{
memset(num,0,sizeof(num));
for(int i=0;i<v[x].size();i++){
num[ id[v[x][i]] ]++;
}
sort(v[x].begin(),v[x].end(),cmp);
// cout<<" ---- "<<endl;
// for(int i=0;i<v[x].size();i++){
// cout<<v[x][i];
// }
// cout<<endl;
// cout<<" ----- "<<endl;
return v[x][0];
}
void init()
{
id['A'] = 1; id['2'] = 2;id['3'] = 3;id['4'] = 4;
id['5'] = 5; id['6'] = 6;id['7'] = 7;id['8'] = 8;
id['9'] = 9; id['D'] = 10;id['Q'] = 11;id['J'] = 12;
id['K'] = 13;
}
int main()
{
init();
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%s",C[i]+1);
for(int j=1;j<=4;j++){
v[i].push_back(C[i][j]);
}
}
int winner ;
for(int i=1;i<=n;i++){
if(i == k)continue;
if(is_win(i)){
printf("%d\n",i);
return 0;
}
}
w = now = k;vis[k] = 1;
while(1){
// cout<<endl;
// cout<<now<<endl;
// for(int i=0;i<v[now].size();i++){
// cout<<v[now][i];
// }
// cout<<endl;
// cout<<"w : "<<w<<endl;
if(!vis[now] && w == now){
w = (now == n)?1:now+1;
vis[w] = 1;
if(is_win(1)){
printf("%d\n",1);
return 0;
}
if(is_win(now)){
printf("%d\n",now);
return 0;
}
now = (now == n)?1:now+1;
continue;
}
else{
char ch = ask(now);
// cout<<"ch : "<<ch<<endl;
v[now].erase(v[now].begin());
int b = (now == n)?1:now+1;
v[b].push_back(ch);
}
vis[now] = 0;
if(is_win(1)){
printf("%d\n",1);
return 0;
}
if(is_win(now)){
printf("%d\n",now);
return 0;
}
now = (now == n)?1:now+1;
}
}
G。Problem G Getting Confidence
题目大意:一个矩阵,每行且每列取一个数,使得乘积最大。
这种每行每列的的题首先想到的就应该是网络流,取log乘积转加和就好了。
列 --> 行
至于路径,只要找到正向流量为0的就好了。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int INF=0x3f3f3f3f;
const double DINF=1.0*1e18;
const double eps=1e-8;
struct Edge{
int u,v,w;
double c;
int next;
}e[N];
int ns,n,mt[105][105];
int cnt,head[N];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w,double c){
e[cnt]=Edge{u,v,w,c,head[u]};
head[u]=cnt++;
e[cnt]=Edge{v,u,0,-c,head[v]};
head[v]=cnt++;
}
double d[N];
int inq[N],s,t,p[N],a[N];
bool bf(int &flow,double &cost){
for(int i=0;i<ns;i++){
d[i]=DINF;
inq[i]=0;
}
d[s]=0;
p[s]=0;
a[s]=INF;
queue<int> q;
q.push(s);
inq[s]=1;
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=false;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
int w=e[i].w;
double c=e[i].c;
if(w>0 && d[v]>d[u]+c){
d[v]=d[u]+c;
p[v]=i;
a[v]=min(a[u],w);
if(!inq[v]){
q.push(v);
inq[v]=1;
}
}
}
}
if(fabs(d[t]-DINF)<eps){
return 0;
}
flow+=a[t];
cost+=d[t]*a[t];
for(int u=t;u!=s;u=e[p[u]].u){
e[p[u]].w-=a[t];
e[p[u]^1].w+=a[t];
}
return 1;
}
void mcmf(int &flow,double &cost){
flow=0;
cost=0.0;
while(bf(flow,cost));
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&mt[i][j]);
}
}
ns=2*n+2;
s=0,t=ns-1;
init();
for(int i=1;i<=n;i++){
add(s,i,1,0.0);
}
for(int i=1;i<=n;i++){
add(n+i,t,1,0.0);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
add(i,n+j,1,-log10(mt[j][i]));
}
}
int flow=0;
double cost=0;
mcmf(flow,cost);
for(int i=1;i<=n;i++){
for(int j=head[i];j!=-1;j=e[j].next){
if(e[j].w==0){
printf("%d",(e[j].v)-n);
if(i==n){
printf("\n");
}else{
printf(" ");
}
break;
}
}
}
return 0;
}
真的不知道自己在干嘛,真懵逼。
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !
I self-criticism three thousand ! ! !