題面:
有 n 個零件需要加工。零件之間有 m 個限制,x->y 表示 x 要在 y 之前先加工完。每個零件的加工時間都是 1。現在有無限個多個工具機,在滿足限制條件的情況下,零件可以同時加工。求加工完所有零件最少需要多少時間,然後還要求出在時間最少的前提下,最少需要多少工具機。資料保證有解。
對於 100%的資料,1<=n<=200,1<=m<=2000;
做法:題目保證有解,說明是乙個dag。
首先,最少的時間比較好求,只需要對於第乙個點進行拓撲排序就行了。
那麼容易發現,第二個答案是不超過n的,考慮從1到n列舉,直到某乙個可行就返回ans2
關鍵問題在於如何判斷。
如何判斷呢?
貪心地,一定是工序長的先在前面的工具機。
那麼我們可以先來一次倒的拓撲(第一問也同樣求進去),得到每個點到工序結束的距離
正著的時候,考慮乙個乙個把節點壓入優先佇列,每次要做的時候,取出優先佇列中最大的ans2個。
然後對這ans2個擴充套件(元素不到ans2個跳出)。
注意到,時間複雜度是o((n+m) + n * (n log n + m)) <=500000——考慮到stl的堆常數較大,但還是夠的(但是方便qaq)
**:
#include#include#include#include#include#include#includeusing namespace std;
const int maxn = 205;
const int maxm = 2005;
struct edgeedge[maxm];
int first[maxn],nume;
void add_edge(int a,int b)
int a[maxm],b[maxm],mark[maxn];
int in[maxn];
int n,m,len;
int down()
int front,rear,q[maxn];
front = rear = 0;
for (int i=1;i<=n;i++)
if (in[i] == 0)
while (front < rear)
} }len = 0;
for (int i=1;i<=n;i++)
return len;
}struct cmp
};bool vis[maxn];
bool check(int m)
memset(vis,false,sizeof(vis));
int tmp[maxn];
for (int i=1;i<=len;i++)
for (int j=1;j<=tmp[0];j++)
}// for (int j=1;j<=n;j++) printf("%d ",in[j]);puts("");
} // puts("");
for (int i=1;i<=n;i++)
if (!vis[i]) return false;
return true;
}int up()
for (int i=1;i<=n;i++)
return -1;
}int main()
printf("%d ",down());
// puts("");
printf("%d\n",up());
}
注意到,這個演算法是錯的,但是隨機資料基本可過,特殊構造資料過的概率還是有點大的。
o-->o-->o-->o
x-->o
o-->y-->o
o-->y-->o
x到2個y都有一條邊。
零件加工(貪心)
時間限制 1 sec 記憶體限制 128 mb 題目描述 工匠小k最近有n個零件需要加工。每個零件都需要ti天的時間來完成,每個零件每延遲一天加工都要繳納一定的罰金si。延遲的天數為從今天算起到該工作開始的那天,第乙個零件加工沒有罰金。現在小k想知道怎樣安排加工順序可以使他要交的罰金最少,最少是多少...
零件加工 貪心 題解
時間限制 1 sec 記憶體限制 128 mb 提交 24 解決 7 提交 狀態 討論版 命題人 外部匯入 題目描述 工匠小k最近有n個零件需要加工。每個零件都需要ti天的時間來完成,每個零件每延遲一天加工都要繳納一定的罰金si。延遲的天數為從今天算起到該工作開始的那天,第乙個零件加工沒有罰金。現在...
NOIP 加工零件 題解
加工零件凱凱的工廠正在有條不紊地生產一種神奇的零件,神奇的零件的生產過程自然也很神奇。工廠裡有 nn 位工人,工人們從 1 sim n1 n 編號。某些工人之間存在雙向的零件傳送帶。保證每兩名工人之間最多隻存在一條傳送帶。如果 xx 號工人想生產乙個被加工到第 l l gt 1 l l 1 階段的零...