NOIP2017解题报告
啊不小心点发布了,懒得删了就这样吧,虽然还没写完,也不打算写了大概。
d1t1
结论题 没什么好说的
d1t2
模拟 没什么好说的
d1t3
70分算法其实比较好想。
没有0边,就跑最短路,然后按dis从小到大转移。
场上最后十分钟才发现单向边,就没时间考虑0边,并且相当于傻逼一样排了个序,水了60;
肯定不能直接排序呀 n*k*log爆了啊,只把n个点按dis排序,然后先枚举一个k即可,肯定是从k小的转移到大的。
然后0边重新建图,拓扑排序,看环上有没有可行解,有就输出-1。否则把拓扑序作为第二关键字排序,转移即可。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=100005;
const int M=200005;
typedef long long LL;
using namespace std; int T,n,m,k,p;
LL dp[N][51]; template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int fir[N],nxt[M],to[M],val[M],ecnt;
int fif[N],nxf[M],tf[M],vaf[M],ecnf;
void add(int u,int v,int w) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
nxf[++ecnf]=fif[v]; fif[v]=ecnf; tf[ecnf]=u; vaf[ecnf]=w;
} int fi[N],nx[M],tt[M],in[N],ec;
void Add(int u,int v) {
nx[++ec]=fi[u]; fi[u]=ec; tt[ec]=v; in[v]++;
} queue<int>que;
int ds[N],dt[N],vis[N],tps[N];
void spfa(int s,int d[],int fir[],int nxt[],int to[],int val[]) {
d[s]=0;
vis[s]=1;
que.push(s);
while(!que.empty()) {
int x=que.front();
que.pop();
vis[x]=0;
for(int i=fir[x];i;i=nxt[i])
if(d[to[i]]>d[x]+val[i]) {
d[to[i]]=d[x]+val[i];
if(!vis[to[i]]) {
vis[to[i]]=1;
que.push(to[i]);
}
}
}
} int tpsort() {
for(int i=1;i<=n;i++) if(!in[i]) que.push(i);
int idd=0;
while(!que.empty()) {
int x=que.front();
que.pop();
tps[x]=++idd;
for(int i=fi[x];i;i=nx[i]) {
if(!(--in[tt[i]]))
que.push(tt[i]);
}
}
for(int i=1;i<=n;i++)
if(in[i]&&ds[i]+dt[i]<=ds[n]+k)
return 1;
return 0;
} struct node{
int x;
friend bool operator <(const node &A,const node &B) {
return ds[A.x]==ds[B.x]?tps[A.x]<tps[B.x]:ds[A.x]<ds[B.x];
}
}po[N*50]; void clear() {
ecnt=ec=ecnf=0;
memset(dt,127,sizeof(dt));
memset(ds,127,sizeof(ds));
memset(fi,0,sizeof(fir));
memset(fir,0,sizeof(fir));
memset(fif,0,sizeof(fif));
memset(in,0,sizeof(in));
memset(tps,0,sizeof(tps));
memset(dp,0,sizeof(dp));
} void work() {
spfa(1,ds,fir,nxt,to,val);
spfa(n,dt,fif,nxf,tf,vaf);
if(tpsort()) printf("-1\n");
else {
int tot=0;
for(int i=1;i<=n;i++)
po[++tot].x=i;
dp[1][0]=1;
sort(po+1,po+tot+1);
for(int y=0;y<=k;y++) {
for(int o=1;o<=tot;o++) {
int x=po[o].x;
for(int i=fir[x];i;i=nxt[i])
if((LL)ds[x]+y+val[i]+dt[to[i]]<=ds[n]+k) {
(dp[to[i]][ds[x]+y+val[i]-ds[to[i]]]+=dp[x][y])%=p;
}
}
}
LL ans=0;
for(int i=0;i<=k;i++) (ans+=dp[n][i])%=p;
printf("%lld\n",ans);
}
} void init() {
read(T);
while(T--) {
clear();
read(n);
read(m);
read(k);
read(p);
for(int i=1;i<=m;i++) {
int u,v,w;
read(u); read(v); read(w);
if(!w) Add(u,v);
add(u,v,w);
}
work();
}
} #define DEBUG
int main() {
#ifdef DEBUG
freopen("park.in","r",stdin);
freopen("park.out","w",stdout);
#endif
init();
return 0;
}
d2t1
并查集
之前在长一考了一道有点像的二维的用并查集这样搞可以水80;
d2t2
一眼状压,然后不会。
推了半个小时prufer数列,并没有什么用。
自己对dp的理解还是太粗浅了。
一个可做的方法是,枚举层数,枚举状态,枚举补集,暴力转移。
你觉得十分不科学,然而事实是这样是可以得出正确答案的。
几个事。
1。不一定全部的状态或者转移都是最优的,只要最终可以达到最优解即可。
2。注意细节,如果层数枚举到12然后空间只开13你不就越界了嘛。。
3。省略一些不用的转移,比如dp==inf时直接略过,不然会死亡tle。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
#define inf 0x7fffffff
typedef long long LL;
using namespace std;
const int N=13;
int n,m,dis[N][N];
LL dp[N][1<<N]; template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
} int q1[N],q2[N],t1,t2;
LL cal(int s,int t) {
t1=t2=0;
LL res=0;
for(int i=1;i<=n;i++) {
if(s&(1<<(i-1))) q1[++t1]=i;
if(t&(1<<(i-1))) q2[++t2]=i;
}
for(int i=1;i<=t2;i++) {
int tp=1e9;
for(int j=1;j<=t1;j++)
tp=min(tp,dis[q2[i]][q1[j]]);
res+=tp;
}
return res;
} void work() {
int nn=(1<<n)-1;
LL ans=1e9;
for(int i=0;i<=n;i++)
for(int j=0;j<=nn;j++)
dp[i][j]=inf;
for(int i=1;i<=n;i++) dp[1][1<<(i-1)]=0;
for(int i=1;i<n;i++) {
for(int s=1;s<=nn;s++) if(dp[i][s]!=inf){
int bj=nn^s;
for(int vv=bj;vv;vv=(vv-1)&bj)
dp[i+1][s|vv]=min(dp[i+1][s|vv],dp[i][s]+i*cal(s,vv));
}
ans=min(ans,dp[i][nn]);
}
ans=min(ans,dp[n][nn]);
printf("%lld\n",ans);
} void init() {
read(n);
read(m);
memset(dis,127/3,sizeof(dis));
for(int i=1;i<=m;i++) {
int u,v,w;
read(u); read(v); read(w);
dis[u][v]=min(dis[u][v],w);
dis[v][u]=dis[u][v];
}
} int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
init();
work();
return 0;
}
d2t3列队
--------------------2018-10-13upd------------------------
拿splay打了这题
WA了一面的提交记录,连个splay都打不陈展,真是菜哭自己
//Achen
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=3e6+;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,q; template<typename T>void read(T &x) {
char ch=getchar(); T f=; x=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} int rt[N];
int tot,ch[N][],p[N];
LL l[N],r[N],sz[N];
#define lc ch[x][0]
#define rc ch[x][1]
void upd(int x) { sz[x]=sz[lc]+sz[rc]+(r[x]-l[x]+); } void rotate(int x) {
int y=p[x],z=p[y],l=(x==ch[y][]),r=(l^);
if(z) ch[z][y==ch[z][]]=x; p[x]=z;
ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
ch[x][r]=y; p[y]=x;
upd(y); upd(x);
} void splay(int &rt,int x) {
for(;p[x];rotate(x)) {
int y=p[x],z=p[y];
if(z) ((x==ch[y][])^(y==ch[z][]))?rotate(x):rotate(y);
}
rt=x;
} int find(int &rt,int k) {
int x=rt;
for(;;) {
if(sz[lc]+<=k&&sz[lc]+r[x]-l[x]+>=k) { k-=sz[lc]; break; }
if(sz[lc]+r[x]-l[x]+<k) { k-=sz[lc]+r[x]-l[x]+; x=rc; }
else x=lc;
}
splay(rt,x);
if(r[x]!=l[x]) {
if(k==||k==r[x]-l[x]+) {
if(k==) { l[++tot]=l[x]; r[tot]=l[x]; l[x]++; }
else { l[++tot]=r[x]; r[tot]=r[x]; r[x]--; }
}
else {
l[++tot]=l[x]+k; r[tot]=r[x]; r[x]=l[x]+k-;
ch[tot][]=ch[x][]; if(ch[x][]) p[ch[x][]]=tot;
ch[x][]=tot; p[tot]=x;
upd(tot); upd(x);
l[++tot]=l[x]+k-; r[tot]=l[tot];
}
upd(tot);
return tot;
}
else {
if(!lc) { rt=rc; p[rc]=; }
else if(!rc) { rt=lc; p[lc]=; }
else {
int a=lc,b=rc;
p[lc]=p[rc]=;
rt=a; while(ch[a][]) a=ch[a][];
splay(rt,a);
ch[a][]=b; p[b]=a;
upd(a);
}
lc=rc=; upd(x);
return x;
}
} void insert(int &rt,int y) {
if(!rt) { rt=y; return; }
int x=rt;
while(rc) x=rc;
splay(rt,x);
rc=y; p[y]=x; upd(x);
} //#define ANS
int main() {
#ifdef ANS
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n); read(m); read(q);
For(i,,n) {
rt[i]=++tot;
l[tot]=((LL)i-)*m+; r[tot]=(LL)i*m-;
upd(tot);
}
For(i,,n) {
int x=++tot;
l[tot]=r[tot]=(LL)i*m;
upd(tot);
insert(rt[n+],x);
}
For(cas,,q) {
int x,y;
read(x); read(y);
if(y==m) {
int t=find(rt[n+],x);
printf("%lld\n",l[t]);
insert(rt[n+],t);
}
else {
int t1=find(rt[x],y);
int t2=find(rt[n+],x);
printf("%lld\n",l[t1]);
insert(rt[x],t2);
insert(rt[n+],t1);
}
}
Formylove;
}
NOIP2017解题报告的更多相关文章
- NOIP2017普及组解题报告
刚参加完NOIP2017普及,只考了210,于是心生不爽,写下了这篇解题报告...(逃 第一次写博,望dalao们多多指导啊(膜 第一题score,学完helloworld的人也应该都会吧,之前好多人 ...
- 冲刺Noip2017模拟赛5 解题报告——五十岚芒果酱
1. 公约数(gcd) [问题描述] 给定一个正整数,在[,n]的范围内,求出有多少个无序数对(a,b)满足 gcd(a,b)=a xor b. [输入格式] 输入共一行,一个正整数n. [输出格式] ...
- 冲刺Noip2017模拟赛3 解题报告——五十岚芒果酱
题1 素数 [问题描述] 给定一个正整数N,询问1到N中有多少个素数. [输入格式]primenum.in 一个正整数N. [输出格式]primenum.out 一个数Ans,表示1到N中有多少个素 ...
- 冲刺Noip2017模拟赛2 解题报告——五十岚芒果酱
题1 牛跑步(running) [题目描述] 新牛到部队,CG 要求它们每天早上搞晨跑,从 A 农场跑到 B 农场.从 A 农场到 B 农场中有 n- 个路口,分别标上号,A 农场为 号,B 农场为 ...
- 冲刺Noip2017模拟赛1 解题报告——五十岚芒果酱
题1 国际象棋(chess) [问题描述] 有N个人要参加国际象棋比赛,该比赛要进行K场对弈.每个人最多参加2场对弈,最少参加0场对弈.每个人都有一个与其他人都不相同的等级(用一个正整数来表示).在对 ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
随机推荐
- C++开发系列-友元函数 友元类
友元函数 默认一个类的私有属性只能在该类的内部可以直接访问.友元函数申明在内的内部,实现在类的外部可以直接访问类的私有属性. class A1 { public: A1() { a1 = 100; a ...
- 关于underline
1, 有些系统可能看不到下划线的效果,这是不妨按着Alt键看看: 2, underline=#, 数字表示在哪个字母下显示下划线,从0开始
- W: 仓库 “http://ppa.launchpad.net/levi-armstrong/qt-libraries-trusty/ubuntu xenial Release” 没有 Release 文件。
解决办法:将对应的PPA删除掉即可 使用以下命令切换到对应PPA目录: cd /etc/apt/sources.list.dsudo rm levi-armstrong-ubuntu-qt-libra ...
- LUOGU P1313 计算系数 (组合数学)
解题思路 比较简单的题,用二项式定理即可. #include<iostream> #include<cstdio> #include<cstring> #inclu ...
- centos 6.5 安装dotnet core 2.2
.net core 官网地址 https://dotnet.microsoft.com/download 本次安装版本为.net core SDK v2.2.101 1.查看系统版本, 升级系统基本l ...
- 反编译之paktool工具
1.官网配置mac教程https://ibotpeaches.github.io/Apktool/install/ (1)右键选择:链接储存为(命名:apktool,格式:选择所有文件): (2)下载 ...
- Chrome浏览器console控制台不打印任何js错误信息
手欠在Chrome控制台在错误信息,右键:Hide messages from vue 看不到 报错信息 这里删除成 默认的Filter 报错就出现了
- codeforces 1129A2-Toy Train
传送门:QAQQAQ 题意:有1-n个站点,成环形,有一辆运货车,在这个n个站点之间运输糖果,货车只能按照1->n的方向走,到第n个站的时候,又回到的1,现在告诉你有m个运输任务,从x站点运输一 ...
- Cocos2d-x发布Android.mk 导入所有cpp
#traverse all the directory and subdirectorydefine walk $(wildcard $(1)) $(foreach e, $(wildcard $(1 ...
- PKU--1976 A Mini Locomotive (01背包)
题目http://poj.org/problem?id=1976 分析:给n个数,求连续3段和的最大值. 这个题目的思考方式很像背包问题. dp[i][j]表示前i个数字,放在j段的最大值. 如果选了 ...