6.16
记 6.16翻车记。又翻车了 我不知道为什么 。
T1 写了n^2暴力 然后freopen 打错。导致 爆0
T2 写了可持久化trie树 又写了费用流 最后发现是一个最大生成树 然后敲上去 long long没开 爆到30
T3 写的两边dij 没检查 然后A了觉得还行。
原因 对拍写的太多了 导致没有证明自己的算法的正确性就去盲目对拍。这点我是有问题的!
而且没有想好就写 代码 如可持久化trie 或费用流 都是一些没有必要的算法当然也不对的算法。这也是我的问题。
对拍的逻辑有问题 我应该是写完一道题对拍一道题 我是全写完了才对拍的。这是我的策略出现了问题。
到最后了不能再改算法了应该全力检查纵使第2题爆零我第一题是可以A的。这是我的认真出现了问题。
感觉没救了 我也不知为何突然烦躁。可能 我应该非常的认真起来了吧。做一个优秀的人!
谁没有翻过车 翻车不铭记的那叫sb。考的题都比较简单没有考有深度的算法 算是对前面的算法进行复习吧,当然这也有一定的原因是学的太多的缘故。
T1 :
看起来是一个n^2暴力其实这题出的没有任何意义,n^2可过是非常无聊的。当然除了我这个freopen打错的人。
正解:我认为这是一个 tarjan求强联通分量+缩点+反向拓扑排序可做的 时间复杂度nlogn级别的当然 精确一点是n*n/32 这也近乎是nlogn
//#include<bits/stdc++.h> #include<iomanip> #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<deque> #include<cmath> #include<ctime> #include<cstdlib> #include<stack> #include<algorithm> #include<vector> #include<cctype> #include<utility> #include<set> #include<bitset> #include<map> #define INF 1000000000 #define ll long long #define min(x,y) ((x)>(y)?(y):(x)) #define max(x,y) ((x)>(y)?(x):(y)) #define RI register ll #define db double using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } inline void put(int x) { x<0?x=-x,putchar('-'):0; int num=0;char ch[20]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar('\n');return; } const int MAXN=5010; int n,m,cnt,top,len,len1,t,h,w; bitset<MAXN>q[MAXN]; int dfn[MAXN],low[MAXN],vis[MAXN],c[MAXN]; int que[MAXN],ru[MAXN],s[MAXN],ans[MAXN]; int lin[MAXN],ver[MAXN],nex[MAXN]; int lc[MAXN],vc[MAXN],nc[MAXN]; inline void add(int x,int y) { ver[++len]=y; nex[len]=lin[x]; lin[x]=len; } inline void cadd(int x,int y) { vc[++len1]=y; nc[len1]=lc[x]; lc[x]=len1; } inline void dfs(int x) { dfn[x]=low[x]=++cnt; vis[x]=1;s[++top]=x; for(int i=lin[x];i;i=nex[i]) { int tn=ver[i]; if(!dfn[tn]) { dfs(tn); low[x]=min(low[x],low[tn]); } else if(vis[tn])low[x]=min(low[x],dfn[tn]); } if(dfn[x]==low[x]) { ++w;int y; do { y=s[top--],vis[y]=0; c[y]=w;q[w][y]=1; }while(x!=y); } } inline void topsort() { for(int i=1;i<=w;++i)if(!ru[i])que[++t]=i; while(h++<t) { int x=que[h]; for(int i=lc[x];i;i=nc[i]) { int tn=vc[i]; q[tn]|=q[x]; --ru[tn]; if(!ru[tn])que[++t]=tn; } } } int main() { freopen("1.in","r",stdin); n=read();m=read(); for(int i=1;i<=m;++i) { int x,y; x=read();y=read(); add(x,y); } for(int i=1;i<=n;++i)if(!dfn[i])dfs(i); for(int i=1;i<=n;++i) { for(int j=lin[i];j;j=nex[j]) { int tn=ver[j]; if(c[i]==c[tn])continue; cadd(c[tn],c[i]);++ru[c[i]]; } } topsort();top=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=cnt;++i)if((int)q[i].count()==n)vis[i]=1; for(int i=1;i<=n;++i)if(vis[c[i]])ans[++top]=i; if(!top){put(top);return 0;} put(top); for(int i=1;i<top;++i)printf("%d ",ans[i]); printf("%d",ans[top]); return 0; }
VFK 曾经说过 暴力A了就A了 用暴力A掉此题的人对他没有任何好处 对我也更没坏处。
这看起来像是一个trie树我在写的时候没有想到严格的 拓扑序关系 写完了可持久化trie 发现过了样例 当时我就发现要开long long 了可惜最后没看见。
显然是有环的对吧 然后还有一个条件 一个战队至少要比一次, 有些战队可以比多次。那就看他们之间的关系了。
发现对于一个环我们可以把其中一条边拆掉 因为这条边权值最小也就不成环了只有 有一个严格的拓扑序的才满足题意。
于是 做法就出来了这个过程无疑是在生成一棵最大的生成树。至于一些不必要的算法那就是不必要。
//#include<bits/stdc++.h> #include<iomanip> #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<deque> #include<cmath> #include<ctime> #include<cstdlib> #include<stack> #include<algorithm> #include<vector> #include<cctype> #include<utility> #include<set> #include<bitset> #include<map> #define INF 1000000000 #define ll long long #define min(x,y) (x>y?y:x) #define max(x,y) (x>y?x:y) #define RI register ll #define up(p,i,n) for(ll i=p;i<=n;++i) #define db double using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline ll read() { ll x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } inline void put(ll x) { x<0?x=-x,putchar('-'):0; ll num=0;char ch[20]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar('\n');return; } const int MAXN=2010,maxn=4000010; ll n,p,m,s,N,S,T,sum,len,cnt; int a[2010],c[2010][2010]; int f[MAXN]; struct wy { ll x,y,z; ll friend operator <(wy a,wy b) { return a.z>b.z; } }t[maxn]; inline ll cmp(ll x,ll y){return x>y;} inline ll getfather(ll x){return f[x]==x?x:f[x]=getfather(f[x]);} int main() { //freopen("bull.in","r",stdin); //freopen("bull.out","w",stdout); //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); n=read();S=n<<1|1;T=S+1; for(ll i=1;i<=n;++i)a[i]=read(); for(ll i=1;i<=n;++i) for(ll j=1;j<=i;++j) { c[i][j]=a[i]^a[j]; t[++cnt]=(wy){i,j,c[i][j]}; } sort(t+1,t+1+cnt); for(ll i=1;i<=n;++i)f[i]=i; for(ll i=1;i<=cnt;++i) { ll xx=getfather(t[i].x); ll yy=getfather(t[i].y); if(xx==yy)continue; f[xx]=yy; sum+=t[i].z; ++len; if(len==n-1)break; } put(sum); return 0; }
这可能是最水的题了 两遍dij 再取个max 很稳!
//#include<bits/stdc++.h> #include<iomanip> #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #include<deque> #include<cmath> #include<ctime> #include<cstdlib> #include<stack> #include<algorithm> #include<vector> #include<cctype> #include<utility> #include<set> #include<bitset> #include<map> #define INF 1000000000 #define ll long long #define min(x,y) ((x)>(y)?(y):(x)) #define max(x,y) ((x)>(y)?(x):(y)) #define RI register ll #define db double using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } inline void put(int x) { x<0?x=-x,putchar('-'):0; int num=0;char ch[20]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar('\n');return; } const int MAXN=10010; int n,m,T,len,maxx; struct wy { int x,y,z; }t[MAXN]; int dis[MAXN],f[MAXN],vis[MAXN]; int lin[MAXN],nex[MAXN],ver[MAXN],e[MAXN]; priority_queue<pair<int,int> > q; inline void add(int x,int y,int z) { ver[++len]=y; nex[len]=lin[x]; lin[x]=len; e[len]=z; } inline void dij(int x) { for(int i=1;i<=n;++i)dis[i]=INF,vis[i]=0; dis[x]=0;q.push(make_pair(dis[x],x)); while(q.size()) { int te=q.top().second; q.pop(); if(vis[te])continue; vis[te]=1; for(int i=lin[te];i;i=nex[i]) { int tn=ver[i]; if(vis[tn])continue; if(dis[tn]>dis[te]+e[i]) { dis[tn]=dis[te]+e[i]; q.push(make_pair(-dis[tn],tn)); } } } } int main() { //freopen("1.in","r",stdin); //freopen("party.in","r",stdin); //freopen("party.out","w",stdout); n=read();m=read();T=read(); for(int i=1;i<=m;++i) { int x,y,z; x=read();y=read();z=read(); t[i]=(wy){x,y,z}; add(x,y,z); } dij(T); for(int i=1;i<=n;++i)f[i]=dis[i]; memset(lin,0,sizeof(lin));len=0; for(int i=1;i<=m;++i)add(t[i].y,t[i].x,t[i].z); dij(T); for(int i=1;i<=n;++i) { //cout<<dis[i]+f[i]<<endl; maxx=max(maxx,dis[i]+f[i]); } put(maxx); return 0; }
题目难度?普及?是我太菜了