1 solutions

  • 0
    @ 2023-11-7 13:13:12

    难度:

    算法: 强连通分量相关

    说句实话,强连通分量的代码量是真多。第一次写到 100 行。

    进入正题。首先跑强连通分量,缩点。对于一个强连通分量,记录这个强连通分量能否被直接购买,购买所需的最少资金,以及最小号码。

    显然,所有入度为 00 的点都必须买,并且只需要买入度为 00 的节点。如果全都能买,那么有解,输出费用即可。如果某些点不能买,说明无解,然后跑一遍搜索:

    以所有能买的节点为起点进行搜索,所有搜不到的节点的最小编号就是第二问答案:

    代码实现较为复杂,请耐心调。

    #include<bits/stdc++.h>
    using namespace std;
    int n,p,m,a,b,pt[3030],c[3030],f[3030],g[3030],r[3030],vis[3030],ans,mn=10000000,te;
    int l[3030],d[3030],in[3030],s[3030],h,t;
    vector<int> e[3030],k[3030];
    priority_queue<int> q[3030];
    stack<int> st;
    void tarj(int u){
    	l[u]=d[u]=++h;
    	st.push(u);
    	in[u]=1;
    	for(int i=0;i<int(e[u].size());i++){
    		int v=e[u][i];
    		if(!d[v]){
    			tarj(v);
    			l[u]=min(l[u],l[v]);
    		}
    		else if(in[v]) l[u]=min(l[u],d[v]);
    	}
    	if(l[u]==d[u]){
    		t++;
    		while(1){
    			s[st.top()]=t;
    			in[st.top()]=0;
    			if(st.top()==u){
    				st.pop();
    				break;
    			}
    			st.pop();
    		}
    	}
    }
    void dfs(int u){
    	if(vis[u]) return ;
    	vis[u]=1;
    	for(int i=0;i<int(k[u].size());i++){
    		int v=k[u][i];
    		dfs(v);
    	}
    }
    int main(){
    	memset(c,0x3f3f3f,sizeof(c));
    	memset(f,0x3f3f3f,sizeof(f));
    	memset(g,0x3f3f3f,sizeof(g));
    	ios::sync_with_stdio(0);
    	cin>>n>>p;
    	for(int i=1;i<=p;i++){
    		cin>>a>>b;
    		c[a]=b;
    	}
    	cin>>m;
    	for(int i=1;i<=m;i++){
    		cin>>a>>b;
    		e[a].push_back(b);
    	}
    	for(int i=1;i<=n;i++){
    		if(!d[i]) tarj(i);
    	}
    	for(int i=1;i<=n;i++){
    		f[s[i]]=min(f[s[i]],c[i]);
    		g[s[i]]=min(g[s[i]],i);
    	}
    	for(int i=1;i<=n;i++){
    		if(c[i]<c[0]) r[s[i]]=1;
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=0;j<int(e[i].size());j++){
    			if(s[i]!=s[e[i][j]]){
    				q[s[i]].push(s[e[i][j]]);
    			} 
    		}
    	} 
    	n=t;
    	for(int i=1;i<=n;i++){
    		while(!q[i].empty()){
    			te=q[i].top();
    			k[i].push_back(te);
    			pt[te]++;
    			while(!q[i].empty()){
    				if(q[i].top()==te) q[i].pop();
    				else break;
    			}
    		} 
    	}
    	for(int i=1;i<=n;i++){
    		if(r[i]) dfs(i);
    	}
    	for(int i=1;i<=n;i++){
    		if(pt[i]==0){
    			if(r[i]==0){
    				ans=-1;
    				break;
    			}
    			ans+=f[i];
    		}
    	}
    	if(ans>=0){
    		cout<<"YES\n"<<ans;
    		return 0;
    	}
    	for(int i=1;i<=n;i++){
    		if(vis[i]==0) mn=min(mn,g[i]);
    	}
    	cout<<"NO\n"<<mn;
    }
    
    • 1

    Information

    ID
    97
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    9
    Tags
    # Submissions
    23
    Accepted
    2
    Uploaded By